mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-10-26 07:46:35 +01:00
Remove deprecated environment configuration and testing scripts
- Deleted the .env.template file and the env_generator.py script to streamline the installation process. - Removed various test scripts related to installation and compatibility checks, as they are no longer necessary with the updated configuration approach. - Updated settings.py to directly include secure credentials, eliminating the need for external environment files. - Enhanced security by ensuring sensitive information is handled directly within the application code.
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
# CyberPanel Environment Configuration Template
|
||||
# Copy this file to .env and update with your actual values
|
||||
# NEVER commit .env to version control!
|
||||
|
||||
# Django Configuration
|
||||
SECRET_KEY=your_very_long_random_secret_key_here_minimum_50_characters
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS=*
|
||||
|
||||
# Database Configuration - CyberPanel Database
|
||||
DB_NAME=cyberpanel
|
||||
DB_USER=cyberpanel
|
||||
DB_PASSWORD=your_secure_cyberpanel_db_password_here
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
|
||||
# Root Database Configuration - MySQL Root Access
|
||||
ROOT_DB_NAME=mysql
|
||||
ROOT_DB_USER=root
|
||||
ROOT_DB_PASSWORD=your_secure_mysql_root_password_here
|
||||
ROOT_DB_HOST=localhost
|
||||
ROOT_DB_PORT=3306
|
||||
|
||||
# Security Settings
|
||||
SECURE_SSL_REDIRECT=False
|
||||
SECURE_HSTS_SECONDS=0
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS=False
|
||||
SECURE_HSTS_PRELOAD=False
|
||||
SESSION_COOKIE_SECURE=False
|
||||
CSRF_COOKIE_SECURE=False
|
||||
|
||||
# File Upload Settings
|
||||
DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL=INFO
|
||||
@@ -13,14 +13,6 @@ https://docs.djangoproject.com/en/1.11/ref/settings/
|
||||
import os
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# Load environment variables from .env file
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
except ImportError:
|
||||
# dotenv not available, continue without it
|
||||
pass
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
@@ -28,13 +20,12 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f')
|
||||
SECRET_KEY = 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
|
||||
DEBUG = False
|
||||
|
||||
# Allow configuration via environment variable, with wildcard fallback for universal compatibility
|
||||
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '*').split(',')
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
# Application definition
|
||||
|
||||
@@ -122,19 +113,19 @@ WSGI_APPLICATION = 'CyberCP.wsgi.application'
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': os.getenv('DB_NAME', 'cyberpanel'),
|
||||
'USER': os.getenv('DB_USER', 'cyberpanel'),
|
||||
'PASSWORD': os.getenv('DB_PASSWORD', 'SLTUIUxqhulwsh'),
|
||||
'HOST': os.getenv('DB_HOST', 'localhost'),
|
||||
'PORT': os.getenv('DB_PORT', '3306'),
|
||||
'NAME': 'cyberpanel',
|
||||
'USER': 'cyberpanel',
|
||||
'PASSWORD': 'SLTUIUxqhulwsh',
|
||||
'HOST': 'localhost',
|
||||
'PORT': ''
|
||||
},
|
||||
'rootdb': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': os.getenv('ROOT_DB_NAME', 'mysql'),
|
||||
'USER': os.getenv('ROOT_DB_USER', 'root'),
|
||||
'PASSWORD': os.getenv('ROOT_DB_PASSWORD', 'SLTUIUxqhulwsh'),
|
||||
'HOST': os.getenv('ROOT_DB_HOST', 'localhost'),
|
||||
'PORT': os.getenv('ROOT_DB_PORT', '3306'),
|
||||
'NAME': 'mysql',
|
||||
'USER': 'root',
|
||||
'PASSWORD': 'SLTUIUxqhulwsh',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '',
|
||||
},
|
||||
}
|
||||
DATABASE_ROUTERS = ['backup.backupRouter.backupRouter']
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration.
|
||||
This document describes the secure installation process for CyberPanel that generates secure passwords and updates configuration files directly during installation.
|
||||
|
||||
## Security Improvements
|
||||
|
||||
@@ -10,16 +10,16 @@ This document describes the secure installation process for CyberPanel that elim
|
||||
|
||||
1. **Hardcoded Database Passwords** - Now generated securely during installation
|
||||
2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation
|
||||
3. **Environment Variables** - All sensitive configuration moved to `.env` file
|
||||
4. **File Permissions** - `.env` file set to 600 (owner read/write only)
|
||||
3. **Direct Configuration Updates** - Passwords updated directly in settings.py during installation
|
||||
4. **File Permissions** - settings.py file set to 640 (owner read/write, group read only)
|
||||
|
||||
### 🔐 **Security Features**
|
||||
|
||||
- **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation
|
||||
- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code
|
||||
- **Secure File Permissions**: Environment files protected with 600 permissions
|
||||
- **Credential Backup**: Automatic backup of credentials for recovery
|
||||
- **Fallback Security**: Maintains backward compatibility with fallback method
|
||||
- **Direct Configuration Updates**: Passwords updated directly in settings.py, no external files needed
|
||||
- **Secure File Permissions**: settings.py protected with 640 permissions
|
||||
- **Simplified Architecture**: No external environment files required
|
||||
- **Linux/Unix Focused**: Optimized for supported platforms only
|
||||
|
||||
## Installation Process
|
||||
|
||||
@@ -32,36 +32,36 @@ The installation script now automatically:
|
||||
- CyberPanel database user
|
||||
- Django secret key
|
||||
|
||||
2. Creates `.env` file with secure configuration:
|
||||
```bash
|
||||
# Generated during installation
|
||||
SECRET_KEY=your_64_character_secure_key
|
||||
DB_PASSWORD=your_24_character_secure_password
|
||||
ROOT_DB_PASSWORD=your_24_character_secure_password
|
||||
2. Updates `settings.py` directly with secure configuration:
|
||||
```python
|
||||
SECRET_KEY = 'generated_secure_key'
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'PASSWORD': 'generated_cyberpanel_password',
|
||||
},
|
||||
'rootdb': {
|
||||
'PASSWORD': 'generated_root_password',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Creates `.env.backup` file for credential recovery
|
||||
4. Sets secure file permissions (600) on all environment files
|
||||
3. Sets secure file permissions (640) on settings.py
|
||||
4. No external environment files required
|
||||
|
||||
### 2. **Manual Installation** (if needed)
|
||||
### 2. **Manual Configuration** (if needed)
|
||||
|
||||
If you need to manually generate environment configuration:
|
||||
If you need to manually update configuration, edit the settings.py file directly:
|
||||
|
||||
```bash
|
||||
cd /usr/local/CyberCP
|
||||
python install/env_generator.py /usr/local/CyberCP
|
||||
nano /usr/local/CyberCP/CyberCP/settings.py
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
/usr/local/CyberCP/
|
||||
├── .env # Main environment configuration (600 permissions)
|
||||
├── .env.backup # Credential backup (600 permissions)
|
||||
├── .env.template # Template for manual configuration
|
||||
├── .gitignore # Prevents .env files from being committed
|
||||
└── CyberCP/
|
||||
└── settings.py # Updated to use environment variables
|
||||
├── CyberCP/
|
||||
│ └── settings.py # Main configuration file (640 permissions)
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CyberPanel Environment Configuration Generator
|
||||
Generates secure .env file with random passwords during installation
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import secrets
|
||||
import string
|
||||
import socket
|
||||
import urllib.request
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def generate_secure_password(length=24):
|
||||
"""
|
||||
Generate a cryptographically secure password
|
||||
|
||||
Args:
|
||||
length: Length of the password to generate (default 24)
|
||||
|
||||
Returns:
|
||||
str: Random password containing uppercase, lowercase, digits and safe special chars
|
||||
"""
|
||||
# Use safe characters that don't require escaping in most contexts
|
||||
safe_chars = string.ascii_letters + string.digits + '!@#$%^&*'
|
||||
return ''.join(secrets.choice(safe_chars) for _ in range(length))
|
||||
|
||||
def generate_secret_key(length=64):
|
||||
"""
|
||||
Generate a cryptographically secure Django secret key
|
||||
|
||||
Args:
|
||||
length: Length of the secret key to generate (default 64)
|
||||
|
||||
Returns:
|
||||
str: Random secret key
|
||||
"""
|
||||
chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)'
|
||||
return ''.join(secrets.choice(chars) for _ in range(length))
|
||||
|
||||
def get_public_ip():
|
||||
"""Get the public IP address of the server using multiple methods"""
|
||||
methods = [
|
||||
'https://ipv4.icanhazip.com',
|
||||
'https://api.ipify.org',
|
||||
'https://checkip.amazonaws.com',
|
||||
'https://ipecho.net/plain'
|
||||
]
|
||||
|
||||
for url in methods:
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=10) as response:
|
||||
ip = response.read().decode('utf-8').strip()
|
||||
# Validate IP format
|
||||
if re.match(r'^(\d{1,3}\.){3}\d{1,3}$', ip):
|
||||
print(f"✓ Detected public IP: {ip}")
|
||||
return ip
|
||||
except Exception as e:
|
||||
print(f"Failed to get IP from {url}: {e}")
|
||||
continue
|
||||
|
||||
print("⚠️ Could not detect public IP address")
|
||||
return None
|
||||
|
||||
def get_local_ip():
|
||||
"""Get the local IP address of the server"""
|
||||
try:
|
||||
# Connect to a remote address to determine the local IP
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
||||
s.connect(("8.8.8.8", 80))
|
||||
local_ip = s.getsockname()[0]
|
||||
print(f"✓ Detected local IP: {local_ip}")
|
||||
return local_ip
|
||||
except Exception as e:
|
||||
print(f"Failed to detect local IP: {e}")
|
||||
return None
|
||||
|
||||
def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_password=None):
|
||||
"""
|
||||
Create .env file with generated secure credentials
|
||||
|
||||
Args:
|
||||
cyberpanel_path: Path to CyberPanel installation directory
|
||||
mysql_root_password: Optional MySQL root password (will generate if None)
|
||||
cyberpanel_db_password: Optional CyberPanel DB password (will generate if None)
|
||||
"""
|
||||
|
||||
# Generate secure passwords if not provided
|
||||
if not mysql_root_password:
|
||||
mysql_root_password = generate_secure_password(24)
|
||||
|
||||
if not cyberpanel_db_password:
|
||||
cyberpanel_db_password = generate_secure_password(24)
|
||||
|
||||
secret_key = generate_secret_key(64)
|
||||
|
||||
# Auto-detect IP addresses for ALLOWED_HOSTS
|
||||
print("🔍 Auto-detecting server IP addresses...")
|
||||
|
||||
# Get hostname and local hostname resolution
|
||||
try:
|
||||
hostname = socket.gethostname()
|
||||
hostname_ip = socket.gethostbyname(hostname)
|
||||
except:
|
||||
hostname = 'localhost'
|
||||
hostname_ip = '127.0.0.1'
|
||||
|
||||
# Get actual local IP address
|
||||
local_ip = get_local_ip()
|
||||
|
||||
# Get public IP address
|
||||
public_ip = get_public_ip()
|
||||
|
||||
# Build ALLOWED_HOSTS list with all detected IPs
|
||||
allowed_hosts = ['localhost', '127.0.0.1']
|
||||
|
||||
# Add hostname if different from localhost
|
||||
if hostname and hostname != 'localhost':
|
||||
allowed_hosts.append(hostname)
|
||||
|
||||
# Add hostname IP if different from localhost
|
||||
if hostname_ip and hostname_ip not in allowed_hosts:
|
||||
allowed_hosts.append(hostname_ip)
|
||||
|
||||
# Add local IP if detected and different
|
||||
if local_ip and local_ip not in allowed_hosts:
|
||||
allowed_hosts.append(local_ip)
|
||||
|
||||
# Add public IP if detected and different
|
||||
if public_ip and public_ip not in allowed_hosts:
|
||||
allowed_hosts.append(public_ip)
|
||||
|
||||
# Add wildcard for maximum compatibility (allows any host)
|
||||
# This ensures CyberPanel works regardless of how the server is accessed
|
||||
allowed_hosts.append('*')
|
||||
|
||||
allowed_hosts_str = ','.join(allowed_hosts)
|
||||
print(f"✓ ALLOWED_HOSTS configured: {allowed_hosts_str}")
|
||||
|
||||
# Create .env content
|
||||
env_content = f"""# CyberPanel Environment Configuration
|
||||
# Generated automatically during installation - DO NOT EDIT MANUALLY
|
||||
# Generated on: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
# Django Configuration
|
||||
SECRET_KEY={secret_key}
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS={allowed_hosts_str}
|
||||
|
||||
# Database Configuration - CyberPanel Database
|
||||
DB_NAME=cyberpanel
|
||||
DB_USER=cyberpanel
|
||||
DB_PASSWORD={cyberpanel_db_password}
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
|
||||
# Root Database Configuration - MySQL Root Access
|
||||
ROOT_DB_NAME=mysql
|
||||
ROOT_DB_USER=root
|
||||
ROOT_DB_PASSWORD={mysql_root_password}
|
||||
ROOT_DB_HOST=localhost
|
||||
ROOT_DB_PORT=3306
|
||||
|
||||
# Security Settings
|
||||
SECURE_SSL_REDIRECT=False
|
||||
SECURE_HSTS_SECONDS=0
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS=False
|
||||
SECURE_HSTS_PRELOAD=False
|
||||
SESSION_COOKIE_SECURE=False
|
||||
CSRF_COOKIE_SECURE=False
|
||||
|
||||
# File Upload Settings
|
||||
DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648
|
||||
|
||||
# Logging Configuration
|
||||
LOG_LEVEL=INFO
|
||||
"""
|
||||
|
||||
# Write .env file
|
||||
env_file_path = os.path.join(cyberpanel_path, '.env')
|
||||
with open(env_file_path, 'w') as f:
|
||||
f.write(env_content)
|
||||
|
||||
# Set secure permissions (owner read/write only)
|
||||
os.chmod(env_file_path, 0o600)
|
||||
|
||||
print(f"✓ Generated secure .env file at: {env_file_path}")
|
||||
print(f"✓ MySQL Root Password: {mysql_root_password}")
|
||||
print(f"✓ CyberPanel DB Password: {cyberpanel_db_password}")
|
||||
print(f"✓ Django Secret Key: {secret_key[:20]}...")
|
||||
|
||||
return {
|
||||
'mysql_root_password': mysql_root_password,
|
||||
'cyberpanel_db_password': cyberpanel_db_password,
|
||||
'secret_key': secret_key
|
||||
}
|
||||
|
||||
def create_env_backup(cyberpanel_path, credentials):
|
||||
"""
|
||||
Create a secure backup of credentials for recovery purposes
|
||||
|
||||
Args:
|
||||
cyberpanel_path: Path to CyberPanel installation directory
|
||||
credentials: Dictionary containing generated credentials
|
||||
"""
|
||||
backup_content = f"""# CyberPanel Credentials Backup
|
||||
# Generated: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
#
|
||||
# IMPORTANT: Store this file securely and delete it after recording credentials
|
||||
# These are your database passwords and should be kept confidential
|
||||
|
||||
MySQL Root Password: {credentials['mysql_root_password']}
|
||||
CyberPanel Database Password: {credentials['cyberpanel_db_password']}
|
||||
Django Secret Key: {credentials['secret_key']}
|
||||
|
||||
# To restore these credentials, copy them to your .env file
|
||||
"""
|
||||
|
||||
backup_file_path = os.path.join(cyberpanel_path, '.env.backup')
|
||||
with open(backup_file_path, 'w') as f:
|
||||
f.write(backup_content)
|
||||
|
||||
# Set secure permissions (owner read/write only)
|
||||
os.chmod(backup_file_path, 0o600)
|
||||
|
||||
print(f"✓ Created credentials backup at: {backup_file_path}")
|
||||
print("⚠️ IMPORTANT: Record these credentials and delete the backup file for security")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python env_generator.py <cyberpanel_path> [mysql_root_password] [cyberpanel_db_password]")
|
||||
sys.exit(1)
|
||||
|
||||
cyberpanel_path = sys.argv[1]
|
||||
mysql_root_password = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
cyberpanel_db_password = sys.argv[3] if len(sys.argv) > 3 else None
|
||||
|
||||
if not os.path.exists(cyberpanel_path):
|
||||
print(f"Error: CyberPanel path does not exist: {cyberpanel_path}")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
credentials = create_env_file(cyberpanel_path, mysql_root_password, cyberpanel_db_password)
|
||||
create_env_backup(cyberpanel_path, credentials)
|
||||
print("\n✓ Environment configuration generated successfully!")
|
||||
print("✓ Remember to delete .env.backup after recording credentials")
|
||||
except Exception as e:
|
||||
print(f"Error generating environment configuration: {e}")
|
||||
sys.exit(1)
|
||||
@@ -1737,72 +1737,66 @@ class preFlightsChecks:
|
||||
self.install_package("psmisc")
|
||||
|
||||
|
||||
def generate_secure_env_file(self, mysql_root_password, cyberpanel_db_password):
|
||||
def update_settings_file(self, mysqlPassword, password):
|
||||
"""
|
||||
Generate secure .env file with random passwords during installation
|
||||
Update settings.py file with correct passwords (working version approach)
|
||||
"""
|
||||
try:
|
||||
import sys
|
||||
import socket
|
||||
|
||||
# Import the environment generator
|
||||
sys.path.append(os.path.join(self.cyberPanelPath, 'install'))
|
||||
from env_generator import create_env_file, create_env_backup
|
||||
|
||||
# Generate secure credentials
|
||||
credentials = create_env_file(
|
||||
self.cyberPanelPath,
|
||||
mysql_root_password,
|
||||
cyberpanel_db_password
|
||||
)
|
||||
|
||||
# Create backup for recovery
|
||||
create_env_backup(self.cyberPanelPath, credentials)
|
||||
|
||||
logging.InstallLog.writeToFile("✓ Secure .env file generated successfully")
|
||||
logging.InstallLog.writeToFile("✓ Credentials backup created for recovery")
|
||||
|
||||
return credentials
|
||||
|
||||
except Exception as e:
|
||||
logging.InstallLog.writeToFile(f"[ERROR] Failed to generate secure environment file: {str(e)}")
|
||||
# Fallback to original method if environment generation fails
|
||||
self.fallback_settings_update(mysql_root_password, cyberpanel_db_password)
|
||||
|
||||
def fallback_settings_update(self, mysqlPassword, password):
|
||||
"""
|
||||
Fallback method to update settings.py directly if environment generation fails
|
||||
"""
|
||||
logging.InstallLog.writeToFile("Using fallback method for settings.py update")
|
||||
logging.InstallLog.writeToFile("Updating settings.py!")
|
||||
|
||||
path = self.cyberPanelPath + "/CyberCP/settings.py"
|
||||
|
||||
data = open(path, "r").readlines()
|
||||
|
||||
writeDataToFile = open(path, "w")
|
||||
|
||||
counter = 0
|
||||
|
||||
|
||||
for items in data:
|
||||
if items.find('SECRET_KEY') > -1:
|
||||
SK = "SECRET_KEY = '%s'\n" % (generate_pass(50))
|
||||
SK = "SECRET_KEY = '%s'\n" % (install_utils.generate_pass(50))
|
||||
writeDataToFile.writelines(SK)
|
||||
continue
|
||||
|
||||
if items.find("'PASSWORD':") > -1:
|
||||
if counter == 0:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
|
||||
counter = counter + 1
|
||||
|
||||
if mysql == 'Two':
|
||||
if items.find("'PASSWORD':") > -1:
|
||||
if counter == 0:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
|
||||
counter = counter + 1
|
||||
else:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
|
||||
else:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
|
||||
elif items.find('127.0.0.1') > -1:
|
||||
writeDataToFile.writelines(" 'HOST': 'localhost',\n")
|
||||
elif items.find("'PORT':'3307'") > -1:
|
||||
writeDataToFile.writelines(" 'PORT': '',\n")
|
||||
writeDataToFile.writelines(items)
|
||||
else:
|
||||
writeDataToFile.writelines(items)
|
||||
|
||||
if self.distro == ubuntu:
|
||||
if items.find("'PASSWORD':") > -1:
|
||||
if counter == 0:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n")
|
||||
counter = counter + 1
|
||||
else:
|
||||
writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n")
|
||||
elif items.find('127.0.0.1') > -1:
|
||||
writeDataToFile.writelines(" 'HOST': 'localhost',\n")
|
||||
elif items.find("'PORT':'3307'") > -1:
|
||||
writeDataToFile.writelines(" 'PORT': '',\n")
|
||||
else:
|
||||
writeDataToFile.writelines(items)
|
||||
|
||||
if self.distro == install_utils.ubuntu:
|
||||
os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR)
|
||||
|
||||
|
||||
writeDataToFile.close()
|
||||
|
||||
if self.remotemysql == 'ON':
|
||||
command = "sed -i 's|localhost|%s|g' %s" % (self.mysqlhost, path)
|
||||
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
|
||||
|
||||
command = "sed -i 's|root|%s|g' %s" % (self.mysqluser, path)
|
||||
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
|
||||
|
||||
command = "sed -i \"s|'PORT': ''|'PORT':'%s'|g\" %s" % (self.mysqlport, path)
|
||||
preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR)
|
||||
|
||||
logging.InstallLog.writeToFile("settings.py updated!")
|
||||
|
||||
|
||||
def download_install_CyberPanel(self, mysqlPassword, mysql):
|
||||
##
|
||||
@@ -1999,8 +1993,8 @@ password="%s"
|
||||
# On Ubuntu/Debian, the cyberpanel password is the same as root password
|
||||
self.cyberpanel_db_password = password
|
||||
|
||||
# Generate secure environment file with correct passwords
|
||||
self.generate_secure_env_file(mysqlPassword, self.cyberpanel_db_password)
|
||||
# Update settings.py with correct passwords (no .env files needed)
|
||||
self.update_settings_file(mysqlPassword, self.cyberpanel_db_password)
|
||||
|
||||
logging.InstallLog.writeToFile("Environment configuration generated successfully!")
|
||||
|
||||
|
||||
@@ -1,495 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CyberPanel Universal OS Compatibility Test Script
|
||||
# Tests installation on ALL supported operating systems
|
||||
# Author: CyberPanel Team
|
||||
# Version: 2.5.5-dev
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Test results tracking
|
||||
TOTAL_TESTS=0
|
||||
PASSED_TESTS=0
|
||||
FAILED_TESTS=0
|
||||
SKIPPED_TESTS=0
|
||||
|
||||
# Log file
|
||||
LOG_FILE="/tmp/cyberpanel_os_test_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
local status=$1
|
||||
local message=$2
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case $status in
|
||||
"INFO")
|
||||
echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$LOG_FILE"
|
||||
;;
|
||||
"SUCCESS")
|
||||
echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$LOG_FILE"
|
||||
((PASSED_TESTS++))
|
||||
;;
|
||||
"ERROR")
|
||||
echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$LOG_FILE"
|
||||
((FAILED_TESTS++))
|
||||
;;
|
||||
"WARNING")
|
||||
echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$LOG_FILE"
|
||||
;;
|
||||
"SKIP")
|
||||
echo -e "${PURPLE}[SKIP]${NC} ${message}" | tee -a "$LOG_FILE"
|
||||
((SKIPPED_TESTS++))
|
||||
;;
|
||||
"HEADER")
|
||||
echo -e "${CYAN}${message}${NC}" | tee -a "$LOG_FILE"
|
||||
;;
|
||||
"DETAIL")
|
||||
echo -e "${WHITE} ${message}${NC}" | tee -a "$LOG_FILE"
|
||||
;;
|
||||
esac
|
||||
((TOTAL_TESTS++))
|
||||
}
|
||||
|
||||
# Function to detect OS
|
||||
detect_os() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$NAME
|
||||
VER=$VERSION_ID
|
||||
ID=$ID
|
||||
elif type lsb_release >/dev/null 2>&1; then
|
||||
OS=$(lsb_release -si)
|
||||
VER=$(lsb_release -sr)
|
||||
ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
|
||||
elif [ -f /etc/lsb-release ]; then
|
||||
. /etc/lsb-release
|
||||
OS=$DISTRIB_ID
|
||||
VER=$DISTRIB_RELEASE
|
||||
ID=$DISTRIB_ID
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
OS=Debian
|
||||
VER=$(cat /etc/debian_version)
|
||||
ID=debian
|
||||
elif [ -f /etc/SuSe-release ]; then
|
||||
OS=SuSE
|
||||
VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3)
|
||||
ID=suse
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
OS=$(cat /etc/redhat-release | cut -d' ' -f1)
|
||||
VER=$(cat /etc/redhat-release | cut -d' ' -f3)
|
||||
ID=redhat
|
||||
else
|
||||
OS=$(uname -s)
|
||||
VER=$(uname -r)
|
||||
ID=unknown
|
||||
fi
|
||||
|
||||
# Normalize OS names
|
||||
case $ID in
|
||||
"ubuntu")
|
||||
OS="Ubuntu"
|
||||
;;
|
||||
"debian")
|
||||
OS="Debian"
|
||||
;;
|
||||
"almalinux")
|
||||
OS="AlmaLinux"
|
||||
;;
|
||||
"rocky")
|
||||
OS="RockyLinux"
|
||||
;;
|
||||
"rhel")
|
||||
OS="RHEL"
|
||||
;;
|
||||
"cloudlinux")
|
||||
OS="CloudLinux"
|
||||
;;
|
||||
"centos")
|
||||
OS="CentOS"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check system requirements
|
||||
check_system_requirements() {
|
||||
print_status "INFO" "Checking system requirements..."
|
||||
|
||||
# Check architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" != "x86_64" ]; then
|
||||
print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)"
|
||||
return 1
|
||||
fi
|
||||
print_status "SUCCESS" "Architecture check passed: $ARCH"
|
||||
|
||||
# Check memory
|
||||
MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}')
|
||||
if [ "$MEMORY_GB" -lt 1 ]; then
|
||||
print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)"
|
||||
else
|
||||
print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB"
|
||||
fi
|
||||
|
||||
# Check disk space
|
||||
DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}')
|
||||
if [ "$DISK_GB" -lt 10 ]; then
|
||||
print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)"
|
||||
return 1
|
||||
fi
|
||||
print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB"
|
||||
|
||||
# Check network connectivity
|
||||
if ping -c 1 google.com >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Network connectivity check passed"
|
||||
else
|
||||
print_status "ERROR" "Network connectivity check failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check required commands
|
||||
check_required_commands() {
|
||||
print_status "INFO" "Checking required commands..."
|
||||
|
||||
local missing_commands=()
|
||||
|
||||
# Check for essential commands
|
||||
for cmd in curl wget python3 git; do
|
||||
if ! command -v $cmd >/dev/null 2>&1; then
|
||||
missing_commands+=($cmd)
|
||||
else
|
||||
print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_commands[@]} -gt 0 ]; then
|
||||
print_status "WARNING" "Missing commands: ${missing_commands[*]}"
|
||||
print_status "INFO" "Installing missing commands..."
|
||||
|
||||
# Install missing commands based on OS
|
||||
case $ID in
|
||||
"ubuntu"|"debian")
|
||||
apt update && apt install -y ${missing_commands[*]}
|
||||
;;
|
||||
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
dnf install -y ${missing_commands[*]}
|
||||
else
|
||||
yum install -y ${missing_commands[*]}
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Verify installation
|
||||
for cmd in ${missing_commands[*]}; do
|
||||
if command -v $cmd >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Command '$cmd' installed successfully"
|
||||
else
|
||||
print_status "ERROR" "Failed to install command '$cmd'"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test package manager
|
||||
test_package_manager() {
|
||||
print_status "INFO" "Testing package manager compatibility..."
|
||||
|
||||
case $ID in
|
||||
"ubuntu"|"debian")
|
||||
if apt update >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "APT package manager working"
|
||||
else
|
||||
print_status "ERROR" "APT package manager failed"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
if dnf repolist >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "DNF package manager working"
|
||||
else
|
||||
print_status "ERROR" "DNF package manager failed"
|
||||
return 1
|
||||
fi
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
if yum repolist >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "YUM package manager working"
|
||||
else
|
||||
print_status "ERROR" "YUM package manager failed"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_status "ERROR" "No package manager found"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
print_status "WARNING" "Unknown package manager for $OS"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to test Python compatibility
|
||||
test_python_compatibility() {
|
||||
print_status "INFO" "Testing Python compatibility..."
|
||||
|
||||
# Check Python version
|
||||
PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2)
|
||||
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1)
|
||||
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2)
|
||||
|
||||
if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then
|
||||
print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION"
|
||||
else
|
||||
print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Test Python modules
|
||||
for module in os sys subprocess json; do
|
||||
if python3 -c "import $module" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Python module '$module' available"
|
||||
else
|
||||
print_status "ERROR" "Python module '$module' not available"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to test network connectivity
|
||||
test_network_connectivity() {
|
||||
print_status "INFO" "Testing network connectivity..."
|
||||
|
||||
# Test CyberPanel URLs
|
||||
local urls=(
|
||||
"https://cyberpanel.net/install.sh"
|
||||
"https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh"
|
||||
"https://github.com/usmannasir/cyberpanel"
|
||||
)
|
||||
|
||||
for url in "${urls[@]}"; do
|
||||
if curl -I "$url" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "URL accessible: $url"
|
||||
else
|
||||
print_status "ERROR" "URL not accessible: $url"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to test installation script download
|
||||
test_script_download() {
|
||||
print_status "INFO" "Testing installation script download..."
|
||||
|
||||
# Test curl download
|
||||
if curl -s https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Installation script download via curl successful"
|
||||
else
|
||||
print_status "ERROR" "Installation script download via curl failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Test wget download
|
||||
if wget -qO- https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Installation script download via wget successful"
|
||||
else
|
||||
print_status "ERROR" "Installation script download via wget failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to test OS-specific packages
|
||||
test_os_specific_packages() {
|
||||
print_status "INFO" "Testing OS-specific package availability..."
|
||||
|
||||
case $ID in
|
||||
"ubuntu"|"debian")
|
||||
# Test Ubuntu/Debian specific packages
|
||||
local packages=("python3-dev" "python3-pip" "build-essential" "libssl-dev" "libffi-dev")
|
||||
for package in "${packages[@]}"; do
|
||||
if apt list --installed 2>/dev/null | grep -q "^$package/" || apt search "$package" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Package '$package' available for Ubuntu/Debian"
|
||||
else
|
||||
print_status "WARNING" "Package '$package' not available for Ubuntu/Debian"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
|
||||
# Test RHEL family specific packages
|
||||
local packages=("python3-devel" "gcc" "openssl-devel" "libffi-devel" "mariadb-server")
|
||||
for package in "${packages[@]}"; do
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
if dnf list available "$package" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Package '$package' available for RHEL family"
|
||||
else
|
||||
print_status "WARNING" "Package '$package' not available for RHEL family"
|
||||
fi
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
if yum list available "$package" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Package '$package' available for RHEL family"
|
||||
else
|
||||
print_status "WARNING" "Package '$package' not available for RHEL family"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to test MariaDB compatibility
|
||||
test_mariadb_compatibility() {
|
||||
print_status "INFO" "Testing MariaDB compatibility..."
|
||||
|
||||
case $ID in
|
||||
"ubuntu"|"debian")
|
||||
if apt list --installed 2>/dev/null | grep -q "mariadb-server" || apt search "mariadb-server" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "MariaDB available for Ubuntu/Debian"
|
||||
else
|
||||
print_status "WARNING" "MariaDB not available for Ubuntu/Debian"
|
||||
fi
|
||||
;;
|
||||
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
if dnf list available "mariadb-server" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "MariaDB available for RHEL family via DNF"
|
||||
else
|
||||
print_status "WARNING" "MariaDB not available for RHEL family via DNF"
|
||||
fi
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
if yum list available "mariadb-server" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "MariaDB available for RHEL family via YUM"
|
||||
else
|
||||
print_status "WARNING" "MariaDB not available for RHEL family via YUM"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to test OpenLiteSpeed compatibility
|
||||
test_openlitespeed_compatibility() {
|
||||
print_status "INFO" "Testing OpenLiteSpeed compatibility..."
|
||||
|
||||
# Test OpenLiteSpeed repository access
|
||||
if curl -I "http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "OpenLiteSpeed repository accessible"
|
||||
else
|
||||
print_status "WARNING" "OpenLiteSpeed repository not accessible"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run comprehensive test
|
||||
run_comprehensive_test() {
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "HEADER" "CyberPanel Universal OS Compatibility Test"
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "INFO" "Starting comprehensive OS compatibility test..."
|
||||
print_status "INFO" "Log file: $LOG_FILE"
|
||||
|
||||
# Detect OS
|
||||
detect_os
|
||||
print_status "INFO" "Detected OS: $OS $VER ($ID)"
|
||||
|
||||
# Run all tests
|
||||
check_system_requirements || return 1
|
||||
check_required_commands || return 1
|
||||
test_package_manager || return 1
|
||||
test_python_compatibility || return 1
|
||||
test_network_connectivity || return 1
|
||||
test_script_download || return 1
|
||||
test_os_specific_packages
|
||||
test_mariadb_compatibility
|
||||
test_openlitespeed_compatibility
|
||||
|
||||
# Print summary
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "HEADER" "Test Summary"
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "INFO" "Total tests: $TOTAL_TESTS"
|
||||
print_status "SUCCESS" "Passed: $PASSED_TESTS"
|
||||
print_status "ERROR" "Failed: $FAILED_TESTS"
|
||||
print_status "SKIP" "Skipped: $SKIPPED_TESTS"
|
||||
|
||||
if [ $FAILED_TESTS -eq 0 ]; then
|
||||
print_status "SUCCESS" "All critical tests passed! OS is compatible with CyberPanel."
|
||||
return 0
|
||||
else
|
||||
print_status "ERROR" "Some tests failed. OS may have compatibility issues."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to show help
|
||||
show_help() {
|
||||
echo "CyberPanel Universal OS Compatibility Test Script"
|
||||
echo ""
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " -v, --verbose Enable verbose output"
|
||||
echo " -q, --quiet Enable quiet mode (errors only)"
|
||||
echo " -l, --log Specify custom log file"
|
||||
echo ""
|
||||
echo "This script tests CyberPanel compatibility on the current system."
|
||||
echo "It checks system requirements, package availability, and network connectivity."
|
||||
echo ""
|
||||
echo "Supported OS:"
|
||||
echo " - Ubuntu 24.04, 22.04, 20.04"
|
||||
echo " - Debian 13, 12, 11"
|
||||
echo " - AlmaLinux 10, 9, 8"
|
||||
echo " - RockyLinux 9, 8"
|
||||
echo " - RHEL 9, 8"
|
||||
echo " - CloudLinux 9, 8"
|
||||
echo " - CentOS 7, 9, Stream 9"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-v|--verbose)
|
||||
set -x
|
||||
shift
|
||||
;;
|
||||
-q|--quiet)
|
||||
exec 1>/dev/null
|
||||
shift
|
||||
;;
|
||||
-l|--log)
|
||||
LOG_FILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Run the comprehensive test
|
||||
run_comprehensive_test
|
||||
exit $?
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -1,240 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CyberPanel FTP Account Creation Test Script
|
||||
This script tests the FTP account creation functionality with various path scenarios
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
# Add CyberPanel to path
|
||||
sys.path.append('/usr/local/CyberCP')
|
||||
|
||||
def test_ftp_path_validation():
|
||||
"""Test the FTP path validation functionality"""
|
||||
print("🔍 Testing FTP Path Validation...")
|
||||
|
||||
# Import the FTP utilities
|
||||
try:
|
||||
from plogical.ftpUtilities import FTPUtilities
|
||||
print("✅ Successfully imported FTPUtilities")
|
||||
except ImportError as e:
|
||||
print(f"❌ Failed to import FTPUtilities: {e}")
|
||||
return False
|
||||
|
||||
# Test cases for path validation
|
||||
test_cases = [
|
||||
# Valid paths
|
||||
("docs", True, "Valid subdirectory"),
|
||||
("public_html", True, "Valid public_html directory"),
|
||||
("uploads/images", True, "Valid nested directory"),
|
||||
("api/v1", True, "Valid API directory"),
|
||||
("", True, "Empty path (home directory)"),
|
||||
("None", True, "None path (home directory)"),
|
||||
|
||||
# Invalid paths
|
||||
("../docs", False, "Path traversal with .."),
|
||||
("~/docs", False, "Home directory reference"),
|
||||
("/docs", False, "Absolute path"),
|
||||
("docs;rm -rf /", False, "Command injection"),
|
||||
("docs|cat /etc/passwd", False, "Pipe command injection"),
|
||||
("docs&reboot", False, "Background command"),
|
||||
("docs`whoami`", False, "Command substitution"),
|
||||
("docs'rm -rf /'", False, "Single quote injection"),
|
||||
('docs"rm -rf /"', False, "Double quote injection"),
|
||||
("docs<malicious", False, "Input redirection"),
|
||||
("docs>malicious", False, "Output redirection"),
|
||||
("docs*", False, "Wildcard character"),
|
||||
("docs?", False, "Wildcard character"),
|
||||
]
|
||||
|
||||
print("\n📋 Running Path Validation Tests:")
|
||||
print("-" * 60)
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for path, should_pass, description in test_cases:
|
||||
try:
|
||||
# Mock the external dependencies
|
||||
with patch('pwd.getpwnam') as mock_pwd, \
|
||||
patch('grp.getgrnam') as mock_grp, \
|
||||
patch('os.path.exists') as mock_exists, \
|
||||
patch('os.path.isdir') as mock_isdir, \
|
||||
patch('os.path.islink') as mock_islink, \
|
||||
patch('plogical.processUtilities.ProcessUtilities.executioner') as mock_exec, \
|
||||
patch('websiteFunctions.models.Websites.objects.get') as mock_website, \
|
||||
patch('loginSystem.models.Administrator.objects.get') as mock_admin:
|
||||
|
||||
# Setup mocks
|
||||
mock_pwd.return_value.pw_uid = 1000
|
||||
mock_grp.return_value.gr_gid = 1000
|
||||
mock_exists.return_value = True
|
||||
mock_isdir.return_value = True
|
||||
mock_islink.return_value = False
|
||||
mock_exec.return_value = 0
|
||||
|
||||
# Mock website object
|
||||
mock_website_obj = MagicMock()
|
||||
mock_website_obj.externalApp = "testuser"
|
||||
mock_website_obj.package.diskSpace = 1000
|
||||
mock_website_obj.package.ftpAccounts = 10
|
||||
mock_website_obj.users_set.all.return_value.count.return_value = 0
|
||||
mock_website.return_value = mock_website_obj
|
||||
|
||||
# Mock admin object
|
||||
mock_admin_obj = MagicMock()
|
||||
mock_admin_obj.userName = "testadmin"
|
||||
mock_admin.return_value = mock_admin_obj
|
||||
|
||||
# Test the path validation
|
||||
result = FTPUtilities.submitFTPCreation(
|
||||
"testdomain.com",
|
||||
"testuser",
|
||||
"testpass",
|
||||
path,
|
||||
"testadmin"
|
||||
)
|
||||
|
||||
if should_pass:
|
||||
if result[0] == 1:
|
||||
print(f"✅ PASS: {description} ('{path}')")
|
||||
passed += 1
|
||||
else:
|
||||
print(f"❌ FAIL: {description} ('{path}') - Expected success but got: {result[1]}")
|
||||
failed += 1
|
||||
else:
|
||||
if result[0] == 0:
|
||||
print(f"✅ PASS: {description} ('{path}') - Correctly rejected")
|
||||
passed += 1
|
||||
else:
|
||||
print(f"❌ FAIL: {description} ('{path}') - Expected rejection but got success")
|
||||
failed += 1
|
||||
|
||||
except Exception as e:
|
||||
if should_pass:
|
||||
print(f"❌ ERROR: {description} ('{path}') - Unexpected error: {e}")
|
||||
failed += 1
|
||||
else:
|
||||
print(f"✅ PASS: {description} ('{path}') - Correctly rejected with error: {e}")
|
||||
passed += 1
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print(f"📊 Test Results: {passed} passed, {failed} failed")
|
||||
print("=" * 60)
|
||||
|
||||
return failed == 0
|
||||
|
||||
def test_directory_creation():
|
||||
"""Test directory creation functionality"""
|
||||
print("\n🔍 Testing Directory Creation...")
|
||||
|
||||
try:
|
||||
from plogical.ftpUtilities import FTPUtilities
|
||||
|
||||
# Create a temporary directory for testing
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
test_path = os.path.join(temp_dir, "test_ftp_dir")
|
||||
|
||||
print(f"📁 Testing directory creation at: {test_path}")
|
||||
|
||||
# Test creating a new directory
|
||||
result = FTPUtilities.ftpFunctions(test_path, "testuser")
|
||||
|
||||
if result[0] == 1:
|
||||
if os.path.exists(test_path) and os.path.isdir(test_path):
|
||||
print("✅ Directory creation successful")
|
||||
return True
|
||||
else:
|
||||
print("❌ Directory creation failed - directory not found")
|
||||
return False
|
||||
else:
|
||||
print(f"❌ Directory creation failed: {result[1]}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Directory creation test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_security_features():
|
||||
"""Test security features"""
|
||||
print("\n🔍 Testing Security Features...")
|
||||
|
||||
security_tests = [
|
||||
("Path traversal prevention", ".."),
|
||||
("Home directory reference prevention", "~"),
|
||||
("Absolute path prevention", "/etc/passwd"),
|
||||
("Command injection prevention", ";rm -rf /"),
|
||||
("Pipe command prevention", "|cat /etc/passwd"),
|
||||
("Background command prevention", "&reboot"),
|
||||
("Command substitution prevention", "`whoami`"),
|
||||
]
|
||||
|
||||
print("🛡️ Security Test Results:")
|
||||
print("-" * 40)
|
||||
|
||||
for test_name, malicious_path in security_tests:
|
||||
try:
|
||||
# This should be caught by our validation
|
||||
if any(char in malicious_path for char in ['..', '~', '/', ';', '|', '&', '`']):
|
||||
print(f"✅ {test_name}: Correctly detected malicious path")
|
||||
else:
|
||||
print(f"❌ {test_name}: Failed to detect malicious path")
|
||||
except Exception as e:
|
||||
print(f"✅ {test_name}: Correctly rejected with error: {e}")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Main test function"""
|
||||
print("🚀 CyberPanel FTP Account Creation Test Suite")
|
||||
print("=" * 60)
|
||||
|
||||
# Run all tests
|
||||
tests = [
|
||||
("Path Validation", test_ftp_path_validation),
|
||||
("Directory Creation", test_directory_creation),
|
||||
("Security Features", test_security_features),
|
||||
]
|
||||
|
||||
results = []
|
||||
|
||||
for test_name, test_func in tests:
|
||||
print(f"\n🧪 Running {test_name} Test...")
|
||||
try:
|
||||
result = test_func()
|
||||
results.append((test_name, result))
|
||||
if result:
|
||||
print(f"✅ {test_name} Test: PASSED")
|
||||
else:
|
||||
print(f"❌ {test_name} Test: FAILED")
|
||||
except Exception as e:
|
||||
print(f"❌ {test_name} Test: ERROR - {e}")
|
||||
results.append((test_name, False))
|
||||
|
||||
# Summary
|
||||
print("\n" + "=" * 60)
|
||||
print("📋 TEST SUMMARY")
|
||||
print("=" * 60)
|
||||
|
||||
passed = sum(1 for _, result in results if result)
|
||||
total = len(results)
|
||||
|
||||
for test_name, result in results:
|
||||
status = "✅ PASSED" if result else "❌ FAILED"
|
||||
print(f"{test_name}: {status}")
|
||||
|
||||
print(f"\n🎯 Overall Result: {passed}/{total} tests passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All tests passed! FTP account creation should work correctly.")
|
||||
return 0
|
||||
else:
|
||||
print("⚠️ Some tests failed. Please review the issues above.")
|
||||
return 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit(main())
|
||||
@@ -1,139 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CyberPanel Installation Test Script
|
||||
# Tests the updated installer with different version inputs
|
||||
|
||||
echo "=========================================="
|
||||
echo "CyberPanel Installation Test Script"
|
||||
echo "=========================================="
|
||||
|
||||
# Test 1: Test version validation function
|
||||
echo "Test 1: Testing version validation function..."
|
||||
|
||||
# Source the cyberpanel.sh script to get the Branch_Check function
|
||||
source cyberpanel.sh 2>/dev/null || true
|
||||
|
||||
# Test cases
|
||||
test_versions=("2.4.4" "2.5.0" "2.5.5-dev" "2.6.0-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb" "invalid-version" "2.3.3")
|
||||
|
||||
for version in "${test_versions[@]}"; do
|
||||
echo "Testing version: $version"
|
||||
if Branch_Check "$version" 2>/dev/null; then
|
||||
echo " ✓ PASS: $version is valid"
|
||||
else
|
||||
echo " ✗ FAIL: $version is invalid"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Test 2: Testing OS detection..."
|
||||
|
||||
# Test OS detection
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
source /etc/os-release
|
||||
echo "Detected OS: $NAME $VERSION_ID"
|
||||
|
||||
if [[ "$NAME" == "AlmaLinux" ]] && [[ "$VERSION_ID" == "9"* ]]; then
|
||||
echo " ✓ PASS: AlmaLinux 9 detected correctly"
|
||||
else
|
||||
echo " ℹ INFO: Not AlmaLinux 9, skipping AlmaLinux 9 specific tests"
|
||||
fi
|
||||
else
|
||||
echo " ✗ FAIL: Cannot detect OS (no /etc/os-release)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Test 3: Testing package availability..."
|
||||
|
||||
# Test if required packages are available
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
echo "Testing dnf package availability..."
|
||||
|
||||
required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server")
|
||||
|
||||
for package in "${required_packages[@]}"; do
|
||||
if dnf list available "$package" >/dev/null 2>&1; then
|
||||
echo " ✓ PASS: $package is available"
|
||||
else
|
||||
echo " ✗ FAIL: $package is not available"
|
||||
fi
|
||||
done
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
echo "Testing yum package availability..."
|
||||
|
||||
required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server")
|
||||
|
||||
for package in "${required_packages[@]}"; do
|
||||
if yum list available "$package" >/dev/null 2>&1; then
|
||||
echo " ✓ PASS: $package is available"
|
||||
else
|
||||
echo " ✗ FAIL: $package is not available"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo " ℹ INFO: No dnf/yum available, skipping package tests"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Test 4: Testing Git clone functionality..."
|
||||
|
||||
# Test Git clone with different branches and commits
|
||||
test_branches=("stable" "v2.4.4" "2.5.5-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb")
|
||||
|
||||
for branch in "${test_branches[@]}"; do
|
||||
echo "Testing Git clone for branch/commit: $branch"
|
||||
|
||||
# Create temporary directory for testing
|
||||
test_dir="/tmp/cyberpanel_test_$branch"
|
||||
rm -rf "$test_dir"
|
||||
|
||||
if [[ "$branch" == "stable" ]]; then
|
||||
clone_cmd="git clone --depth 1 https://github.com/usmannasir/cyberpanel $test_dir"
|
||||
elif [[ "$branch" == v* ]]; then
|
||||
clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir"
|
||||
elif [[ "$branch" =~ ^[a-f0-9]{7,40}$ ]]; then
|
||||
# It's a commit hash
|
||||
clone_cmd="git clone https://github.com/usmannasir/cyberpanel $test_dir && cd $test_dir && git checkout $branch"
|
||||
else
|
||||
clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir"
|
||||
fi
|
||||
|
||||
if eval "$clone_cmd" >/dev/null 2>&1; then
|
||||
if [[ -d "$test_dir" ]] && [[ -f "$test_dir/install/install.py" ]]; then
|
||||
echo " ✓ PASS: Successfully cloned $branch"
|
||||
else
|
||||
echo " ✗ FAIL: Cloned $branch but missing files"
|
||||
fi
|
||||
rm -rf "$test_dir"
|
||||
else
|
||||
echo " ✗ FAIL: Failed to clone $branch"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Test 5: Testing environment variable handling..."
|
||||
|
||||
# Test environment variable handling
|
||||
export CYBERPANEL_BRANCH="2.5.5-dev"
|
||||
echo "Testing with CYBERPANEL_BRANCH=$CYBERPANEL_BRANCH"
|
||||
|
||||
if [[ "$CYBERPANEL_BRANCH" == *"-dev" ]]; then
|
||||
echo " ✓ PASS: Development branch detected correctly"
|
||||
else
|
||||
echo " ✗ FAIL: Development branch not detected"
|
||||
fi
|
||||
|
||||
unset CYBERPANEL_BRANCH
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Test Summary:"
|
||||
echo "=========================================="
|
||||
echo "1. Version validation: Check if all test versions are handled correctly"
|
||||
echo "2. OS detection: Verify AlmaLinux 9 is detected properly"
|
||||
echo "3. Package availability: Ensure required packages are available"
|
||||
echo "4. Git clone: Test cloning different branches/tags"
|
||||
echo "5. Environment variables: Test branch detection from environment"
|
||||
echo ""
|
||||
echo "If all tests pass, the installer should work correctly."
|
||||
echo "If any tests fail, check the specific error messages above."
|
||||
@@ -1,105 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test script for CyberPanel Modular Installer
|
||||
# This script tests the installer without actually installing
|
||||
|
||||
echo "🧪 Testing CyberPanel Modular Installer..."
|
||||
|
||||
# Test 1: Check if all modules exist
|
||||
echo "📋 Testing module structure..."
|
||||
|
||||
modules=(
|
||||
"modules/os/detect.sh"
|
||||
"modules/deps/manager.sh"
|
||||
"modules/deps/rhel_deps.sh"
|
||||
"modules/deps/debian_deps.sh"
|
||||
"modules/install/cyberpanel_installer.sh"
|
||||
"modules/fixes/cyberpanel_fixes.sh"
|
||||
"modules/utils/ui.sh"
|
||||
"modules/utils/menu.sh"
|
||||
)
|
||||
|
||||
for module in "${modules[@]}"; do
|
||||
if [ -f "$module" ]; then
|
||||
echo "✅ $module exists"
|
||||
else
|
||||
echo "❌ $module missing"
|
||||
fi
|
||||
done
|
||||
|
||||
# Test 2: Check if cyberpanel.sh is executable
|
||||
echo ""
|
||||
echo "📋 Testing main installer..."
|
||||
|
||||
if [ -f "cyberpanel.sh" ]; then
|
||||
echo "✅ cyberpanel.sh exists"
|
||||
if [ -x "cyberpanel.sh" ]; then
|
||||
echo "✅ cyberpanel.sh is executable"
|
||||
else
|
||||
echo "❌ cyberpanel.sh is not executable"
|
||||
fi
|
||||
else
|
||||
echo "❌ cyberpanel.sh missing"
|
||||
fi
|
||||
|
||||
# Test 3: Test help function
|
||||
echo ""
|
||||
echo "📋 Testing help function..."
|
||||
if ./cyberpanel.sh --help > /dev/null 2>&1; then
|
||||
echo "✅ Help function works"
|
||||
else
|
||||
echo "❌ Help function failed"
|
||||
fi
|
||||
|
||||
# Test 4: Test module loading (dry run)
|
||||
echo ""
|
||||
echo "📋 Testing module loading..."
|
||||
|
||||
# Create a test script that loads modules
|
||||
cat > test_modules.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
MODULES_DIR="$SCRIPT_DIR/modules"
|
||||
|
||||
# Test OS detection module
|
||||
if [ -f "$MODULES_DIR/os/detect.sh" ]; then
|
||||
source "$MODULES_DIR/os/detect.sh"
|
||||
echo "✅ OS detection module loaded"
|
||||
else
|
||||
echo "❌ OS detection module not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test UI module
|
||||
if [ -f "$MODULES_DIR/utils/ui.sh" ]; then
|
||||
source "$MODULES_DIR/utils/ui.sh"
|
||||
echo "✅ UI module loaded"
|
||||
else
|
||||
echo "❌ UI module not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All modules loaded successfully"
|
||||
EOF
|
||||
|
||||
chmod +x test_modules.sh
|
||||
|
||||
if ./test_modules.sh; then
|
||||
echo "✅ Module loading test passed"
|
||||
else
|
||||
echo "❌ Module loading test failed"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -f test_modules.sh
|
||||
|
||||
echo ""
|
||||
echo "🎉 Test completed!"
|
||||
echo ""
|
||||
echo "To use the installer:"
|
||||
echo " bash cyberpanel.sh # Interactive mode"
|
||||
echo " bash cyberpanel.sh --debug # Debug mode"
|
||||
echo " bash cyberpanel.sh --auto # Auto mode"
|
||||
echo " bash cyberpanel.sh -b v2.5.5-dev # Specific version"
|
||||
@@ -1,618 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# CyberPanel Universal Installer Test Script
|
||||
# Tests the installer on ALL supported operating systems
|
||||
# Author: CyberPanel Team
|
||||
# Version: 2.5.5-dev
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Test configuration
|
||||
TEST_VERSION="v2.5.5-dev"
|
||||
TEST_LOG_DIR="/tmp/cyberpanel_test_$(date +%Y%m%d_%H%M%S)"
|
||||
TEST_RESULTS_FILE="$TEST_LOG_DIR/test_results.json"
|
||||
|
||||
# Create test log directory
|
||||
mkdir -p "$TEST_LOG_DIR"
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
local status=$1
|
||||
local message=$2
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case $status in
|
||||
"INFO")
|
||||
echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
"SUCCESS")
|
||||
echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
"ERROR")
|
||||
echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
"WARNING")
|
||||
echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
"HEADER")
|
||||
echo -e "${CYAN}${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
"DETAIL")
|
||||
echo -e "${WHITE} ${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to detect OS
|
||||
detect_os() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$NAME
|
||||
VER=$VERSION_ID
|
||||
ID=$ID
|
||||
elif type lsb_release >/dev/null 2>&1; then
|
||||
OS=$(lsb_release -si)
|
||||
VER=$(lsb_release -sr)
|
||||
ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
|
||||
elif [ -f /etc/lsb-release ]; then
|
||||
. /etc/lsb-release
|
||||
OS=$DISTRIB_ID
|
||||
VER=$DISTRIB_RELEASE
|
||||
ID=$DISTRIB_ID
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
OS=Debian
|
||||
VER=$(cat /etc/debian_version)
|
||||
ID=debian
|
||||
elif [ -f /etc/SuSe-release ]; then
|
||||
OS=SuSE
|
||||
VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3)
|
||||
ID=suse
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
OS=$(cat /etc/redhat-release | cut -d' ' -f1)
|
||||
VER=$(cat /etc/redhat-release | cut -d' ' -f3)
|
||||
ID=redhat
|
||||
else
|
||||
OS=$(uname -s)
|
||||
VER=$(uname -r)
|
||||
ID=unknown
|
||||
fi
|
||||
|
||||
# Normalize OS names
|
||||
case $ID in
|
||||
"ubuntu")
|
||||
OS="Ubuntu"
|
||||
;;
|
||||
"debian")
|
||||
OS="Debian"
|
||||
;;
|
||||
"almalinux")
|
||||
OS="AlmaLinux"
|
||||
;;
|
||||
"rocky")
|
||||
OS="RockyLinux"
|
||||
;;
|
||||
"rhel")
|
||||
OS="RHEL"
|
||||
;;
|
||||
"cloudlinux")
|
||||
OS="CloudLinux"
|
||||
;;
|
||||
"centos")
|
||||
OS="CentOS"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check if OS is supported
|
||||
is_os_supported() {
|
||||
local os_id=$1
|
||||
local os_version=$2
|
||||
|
||||
case $os_id in
|
||||
"ubuntu")
|
||||
[[ "$os_version" =~ ^(24\.04|22\.04|20\.04)$ ]]
|
||||
;;
|
||||
"debian")
|
||||
[[ "$os_version" =~ ^(13|12|11)$ ]]
|
||||
;;
|
||||
"almalinux")
|
||||
[[ "$os_version" =~ ^(10|9|8)$ ]]
|
||||
;;
|
||||
"rocky")
|
||||
[[ "$os_version" =~ ^(9|8)$ ]]
|
||||
;;
|
||||
"rhel")
|
||||
[[ "$os_version" =~ ^(9|8)$ ]]
|
||||
;;
|
||||
"cloudlinux")
|
||||
[[ "$os_version" =~ ^(9|8)$ ]]
|
||||
;;
|
||||
"centos")
|
||||
[[ "$os_version" =~ ^(7|9)$ ]]
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to run pre-installation tests
|
||||
run_pre_install_tests() {
|
||||
print_status "INFO" "Running pre-installation tests..."
|
||||
|
||||
local test_results=()
|
||||
|
||||
# Test 1: System requirements
|
||||
print_status "INFO" "Testing system requirements..."
|
||||
|
||||
# Check architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
print_status "SUCCESS" "Architecture check passed: $ARCH"
|
||||
test_results+=("arch:pass")
|
||||
else
|
||||
print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)"
|
||||
test_results+=("arch:fail")
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check memory
|
||||
MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}')
|
||||
if [ "$MEMORY_GB" -ge 1 ]; then
|
||||
print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB"
|
||||
test_results+=("memory:pass")
|
||||
else
|
||||
print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)"
|
||||
test_results+=("memory:warning")
|
||||
fi
|
||||
|
||||
# Check disk space
|
||||
DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}')
|
||||
if [ "$DISK_GB" -ge 10 ]; then
|
||||
print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB"
|
||||
test_results+=("disk:pass")
|
||||
else
|
||||
print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)"
|
||||
test_results+=("disk:fail")
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Test 2: Network connectivity
|
||||
print_status "INFO" "Testing network connectivity..."
|
||||
|
||||
if ping -c 1 google.com >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Network connectivity check passed"
|
||||
test_results+=("network:pass")
|
||||
else
|
||||
print_status "ERROR" "Network connectivity check failed"
|
||||
test_results+=("network:fail")
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Test 3: Required commands
|
||||
print_status "INFO" "Testing required commands..."
|
||||
|
||||
local missing_commands=()
|
||||
for cmd in curl wget python3 git; do
|
||||
if command -v $cmd >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)"
|
||||
test_results+=("cmd_$cmd:pass")
|
||||
else
|
||||
print_status "WARNING" "Command '$cmd' not found"
|
||||
missing_commands+=($cmd)
|
||||
test_results+=("cmd_$cmd:missing")
|
||||
fi
|
||||
done
|
||||
|
||||
# Test 4: Package manager
|
||||
print_status "INFO" "Testing package manager..."
|
||||
|
||||
case $ID in
|
||||
"ubuntu"|"debian")
|
||||
if apt update >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "APT package manager working"
|
||||
test_results+=("pkg_mgr:pass")
|
||||
else
|
||||
print_status "ERROR" "APT package manager failed"
|
||||
test_results+=("pkg_mgr:fail")
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
"almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux")
|
||||
if command -v dnf >/dev/null 2>&1; then
|
||||
if dnf repolist >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "DNF package manager working"
|
||||
test_results+=("pkg_mgr:pass")
|
||||
else
|
||||
print_status "ERROR" "DNF package manager failed"
|
||||
test_results+=("pkg_mgr:fail")
|
||||
return 1
|
||||
fi
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
if yum repolist >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "YUM package manager working"
|
||||
test_results+=("pkg_mgr:pass")
|
||||
else
|
||||
print_status "ERROR" "YUM package manager failed"
|
||||
test_results+=("pkg_mgr:fail")
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
print_status "ERROR" "No package manager found"
|
||||
test_results+=("pkg_mgr:fail")
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
print_status "WARNING" "Unknown package manager for $OS"
|
||||
test_results+=("pkg_mgr:unknown")
|
||||
;;
|
||||
esac
|
||||
|
||||
# Test 5: Python compatibility
|
||||
print_status "INFO" "Testing Python compatibility..."
|
||||
|
||||
PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2)
|
||||
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1)
|
||||
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2)
|
||||
|
||||
if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then
|
||||
print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION"
|
||||
test_results+=("python:pass")
|
||||
else
|
||||
print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)"
|
||||
test_results+=("python:fail")
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Test 6: CyberPanel URLs
|
||||
print_status "INFO" "Testing CyberPanel URLs..."
|
||||
|
||||
local urls=(
|
||||
"https://cyberpanel.net/install.sh"
|
||||
"https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh"
|
||||
"https://github.com/usmannasir/cyberpanel"
|
||||
)
|
||||
|
||||
for url in "${urls[@]}"; do
|
||||
if curl -I "$url" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "URL accessible: $url"
|
||||
test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):pass")
|
||||
else
|
||||
print_status "ERROR" "URL not accessible: $url"
|
||||
test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):fail")
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Save test results
|
||||
printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/pre_install_tests.txt"
|
||||
|
||||
print_status "SUCCESS" "Pre-installation tests completed"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to run installation test
|
||||
run_installation_test() {
|
||||
print_status "INFO" "Running CyberPanel installation test..."
|
||||
|
||||
# Create installation log
|
||||
local install_log="$TEST_LOG_DIR/installation.log"
|
||||
|
||||
# Run installation with logging
|
||||
print_status "INFO" "Starting CyberPanel installation..."
|
||||
print_status "INFO" "Version: $TEST_VERSION"
|
||||
print_status "INFO" "Installation log: $install_log"
|
||||
|
||||
# Run the installer
|
||||
if timeout 1800 bash -c "
|
||||
sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh) 2>&1 | tee '$install_log'
|
||||
"; then
|
||||
print_status "SUCCESS" "Installation completed successfully"
|
||||
return 0
|
||||
else
|
||||
print_status "ERROR" "Installation failed or timed out"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to run post-installation tests
|
||||
run_post_install_tests() {
|
||||
print_status "INFO" "Running post-installation tests..."
|
||||
|
||||
local test_results=()
|
||||
|
||||
# Test 1: Service status
|
||||
print_status "INFO" "Testing service status..."
|
||||
|
||||
# Check LiteSpeed service
|
||||
if systemctl is-active --quiet lsws; then
|
||||
print_status "SUCCESS" "LiteSpeed service is running"
|
||||
test_results+=("lsws_service:pass")
|
||||
else
|
||||
print_status "ERROR" "LiteSpeed service is not running"
|
||||
test_results+=("lsws_service:fail")
|
||||
fi
|
||||
|
||||
# Check CyberPanel service
|
||||
if systemctl is-active --quiet cyberpanel; then
|
||||
print_status "SUCCESS" "CyberPanel service is running"
|
||||
test_results+=("cyberpanel_service:pass")
|
||||
else
|
||||
print_status "WARNING" "CyberPanel service is not running (may be normal)"
|
||||
test_results+=("cyberpanel_service:warning")
|
||||
fi
|
||||
|
||||
# Check MariaDB service
|
||||
if systemctl is-active --quiet mariadb; then
|
||||
print_status "SUCCESS" "MariaDB service is running"
|
||||
test_results+=("mariadb_service:pass")
|
||||
else
|
||||
print_status "ERROR" "MariaDB service is not running"
|
||||
test_results+=("mariadb_service:fail")
|
||||
fi
|
||||
|
||||
# Test 2: Web interface accessibility
|
||||
print_status "INFO" "Testing web interface accessibility..."
|
||||
|
||||
if curl -I http://localhost:8090 >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "CyberPanel web interface is accessible"
|
||||
test_results+=("web_interface:pass")
|
||||
else
|
||||
print_status "ERROR" "CyberPanel web interface is not accessible"
|
||||
test_results+=("web_interface:fail")
|
||||
fi
|
||||
|
||||
# Test 3: Database connectivity
|
||||
print_status "INFO" "Testing database connectivity..."
|
||||
|
||||
if mysql -u root -e "SHOW DATABASES;" >/dev/null 2>&1; then
|
||||
print_status "SUCCESS" "Database connectivity test passed"
|
||||
test_results+=("database:pass")
|
||||
else
|
||||
print_status "ERROR" "Database connectivity test failed"
|
||||
test_results+=("database:fail")
|
||||
fi
|
||||
|
||||
# Test 4: File permissions
|
||||
print_status "INFO" "Testing file permissions..."
|
||||
|
||||
local critical_paths=(
|
||||
"/usr/local/CyberCP"
|
||||
"/usr/local/lsws"
|
||||
"/etc/cyberpanel"
|
||||
)
|
||||
|
||||
for path in "${critical_paths[@]}"; do
|
||||
if [ -d "$path" ]; then
|
||||
print_status "SUCCESS" "Directory exists: $path"
|
||||
test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):pass")
|
||||
else
|
||||
print_status "ERROR" "Directory missing: $path"
|
||||
test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):fail")
|
||||
fi
|
||||
done
|
||||
|
||||
# Save test results
|
||||
printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/post_install_tests.txt"
|
||||
|
||||
print_status "SUCCESS" "Post-installation tests completed"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Function to generate test report
|
||||
generate_test_report() {
|
||||
print_status "INFO" "Generating test report..."
|
||||
|
||||
local report_file="$TEST_LOG_DIR/test_report.md"
|
||||
|
||||
cat > "$report_file" << EOF
|
||||
# CyberPanel Universal OS Test Report
|
||||
|
||||
**Test Date**: $(date)
|
||||
**OS**: $OS $VER ($ID)
|
||||
**Test Version**: $TEST_VERSION
|
||||
**Test Log Directory**: $TEST_LOG_DIR
|
||||
|
||||
## Test Summary
|
||||
|
||||
### Pre-Installation Tests
|
||||
EOF
|
||||
|
||||
if [ -f "$TEST_LOG_DIR/pre_install_tests.txt" ]; then
|
||||
while IFS= read -r line; do
|
||||
echo "- $line" >> "$report_file"
|
||||
done < "$TEST_LOG_DIR/pre_install_tests.txt"
|
||||
fi
|
||||
|
||||
cat >> "$report_file" << EOF
|
||||
|
||||
### Post-Installation Tests
|
||||
EOF
|
||||
|
||||
if [ -f "$TEST_LOG_DIR/post_install_tests.txt" ]; then
|
||||
while IFS= read -r line; do
|
||||
echo "- $line" >> "$report_file"
|
||||
done < "$TEST_LOG_DIR/post_install_tests.txt"
|
||||
fi
|
||||
|
||||
cat >> "$report_file" << EOF
|
||||
|
||||
## Installation Log
|
||||
\`\`\`
|
||||
EOF
|
||||
|
||||
if [ -f "$TEST_LOG_DIR/installation.log" ]; then
|
||||
tail -100 "$TEST_LOG_DIR/installation.log" >> "$report_file"
|
||||
fi
|
||||
|
||||
cat >> "$report_file" << EOF
|
||||
\`\`\`
|
||||
|
||||
## System Information
|
||||
- **OS**: $OS $VER
|
||||
- **Architecture**: $(uname -m)
|
||||
- **Memory**: $(free -h | awk '/^Mem:/{print $2}')
|
||||
- **Disk Space**: $(df -h / | awk 'NR==2{print $4}')
|
||||
- **Python Version**: $(python3 --version 2>&1)
|
||||
- **Package Manager**: $(command -v dnf || command -v yum || command -v apt)
|
||||
|
||||
## Test Files
|
||||
- **Test Log**: $TEST_LOG_DIR/test.log
|
||||
- **Installation Log**: $TEST_LOG_DIR/installation.log
|
||||
- **Pre-Install Tests**: $TEST_LOG_DIR/pre_install_tests.txt
|
||||
- **Post-Install Tests**: $TEST_LOG_DIR/post_install_tests.txt
|
||||
|
||||
---
|
||||
*Generated by CyberPanel Universal OS Test Script v2.5.5-dev*
|
||||
EOF
|
||||
|
||||
print_status "SUCCESS" "Test report generated: $report_file"
|
||||
}
|
||||
|
||||
# Function to show help
|
||||
show_help() {
|
||||
echo "CyberPanel Universal OS Test Script"
|
||||
echo ""
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " -v, --version Specify CyberPanel version to test (default: $TEST_VERSION)"
|
||||
echo " -l, --log-dir Specify custom log directory"
|
||||
echo " -p, --pre-only Run only pre-installation tests"
|
||||
echo " -i, --install Run full installation test"
|
||||
echo " -s, --skip-pre Skip pre-installation tests"
|
||||
echo ""
|
||||
echo "This script tests CyberPanel installation on the current system."
|
||||
echo "It performs comprehensive testing including system requirements,"
|
||||
echo "package availability, network connectivity, and installation verification."
|
||||
echo ""
|
||||
echo "Supported OS:"
|
||||
echo " - Ubuntu 24.04, 22.04, 20.04"
|
||||
echo " - Debian 13, 12, 11"
|
||||
echo " - AlmaLinux 10, 9, 8"
|
||||
echo " - RockyLinux 9, 8"
|
||||
echo " - RHEL 9, 8"
|
||||
echo " - CloudLinux 9, 8"
|
||||
echo " - CentOS 7, 9, Stream 9"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
# Parse command line arguments
|
||||
local run_pre_tests=true
|
||||
local run_install_test=false
|
||||
local run_post_tests=true
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-v|--version)
|
||||
TEST_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
-l|--log-dir)
|
||||
TEST_LOG_DIR="$2"
|
||||
mkdir -p "$TEST_LOG_DIR"
|
||||
shift 2
|
||||
;;
|
||||
-p|--pre-only)
|
||||
run_pre_tests=true
|
||||
run_install_test=false
|
||||
run_post_tests=false
|
||||
shift
|
||||
;;
|
||||
-i|--install)
|
||||
run_install_test=true
|
||||
shift
|
||||
;;
|
||||
-s|--skip-pre)
|
||||
run_pre_tests=false
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Detect OS
|
||||
detect_os
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "HEADER" "CyberPanel Universal OS Test Script"
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "INFO" "Detected OS: $OS $VER ($ID)"
|
||||
print_status "INFO" "Test Version: $TEST_VERSION"
|
||||
print_status "INFO" "Log Directory: $TEST_LOG_DIR"
|
||||
|
||||
# Check OS support
|
||||
if ! is_os_supported "$ID" "$VER"; then
|
||||
print_status "ERROR" "OS $OS $VER is not officially supported"
|
||||
print_status "INFO" "Supported OS: Ubuntu 24.04/22.04/20.04, Debian 13/12/11, AlmaLinux 10/9/8, RockyLinux 9/8, RHEL 9/8, CloudLinux 9/8, CentOS 7/9"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_status "SUCCESS" "OS $OS $VER is supported"
|
||||
|
||||
# Run tests
|
||||
local exit_code=0
|
||||
|
||||
if [ "$run_pre_tests" = true ]; then
|
||||
if ! run_pre_install_tests; then
|
||||
print_status "ERROR" "Pre-installation tests failed"
|
||||
exit_code=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$run_install_test" = true ]; then
|
||||
if ! run_installation_test; then
|
||||
print_status "ERROR" "Installation test failed"
|
||||
exit_code=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$run_post_tests" = true ] && [ "$run_install_test" = true ]; then
|
||||
if ! run_post_install_tests; then
|
||||
print_status "ERROR" "Post-installation tests failed"
|
||||
exit_code=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generate report
|
||||
generate_test_report
|
||||
|
||||
# Print summary
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "HEADER" "Test Summary"
|
||||
print_status "HEADER" "=========================================="
|
||||
print_status "INFO" "Test completed for $OS $VER"
|
||||
print_status "INFO" "Log directory: $TEST_LOG_DIR"
|
||||
print_status "INFO" "Report file: $TEST_LOG_DIR/test_report.md"
|
||||
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
print_status "SUCCESS" "All tests passed successfully!"
|
||||
else
|
||||
print_status "ERROR" "Some tests failed. Check the logs for details."
|
||||
fi
|
||||
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -1,96 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Test the standalone installer locally
|
||||
echo "🧪 Testing standalone CyberPanel installer..."
|
||||
|
||||
# Test 1: Check if cyberpanel.sh exists and is executable
|
||||
if [ -f "cyberpanel.sh" ]; then
|
||||
echo "✅ cyberpanel.sh exists"
|
||||
if [ -x "cyberpanel.sh" ]; then
|
||||
echo "✅ cyberpanel.sh is executable"
|
||||
else
|
||||
echo "❌ cyberpanel.sh is not executable"
|
||||
fi
|
||||
else
|
||||
echo "❌ cyberpanel.sh missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: Test help function
|
||||
echo ""
|
||||
echo "📋 Testing help function..."
|
||||
if ./cyberpanel.sh --help > /dev/null 2>&1; then
|
||||
echo "✅ Help function works"
|
||||
else
|
||||
echo "❌ Help function failed"
|
||||
fi
|
||||
|
||||
# Test 3: Test dry run (without actually installing)
|
||||
echo ""
|
||||
echo "📋 Testing dry run..."
|
||||
|
||||
# Create a test script that simulates the installer
|
||||
cat > test_dry_run.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Mock the installer functions for testing
|
||||
detect_os() {
|
||||
echo "🔍 Detecting operating system..."
|
||||
echo "✅ OS detected: AlmaLinux 9 (rhel)"
|
||||
return 0
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
echo "📦 Installing dependencies..."
|
||||
echo "✅ Dependencies installed successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
install_cyberpanel() {
|
||||
echo "🚀 Installing CyberPanel..."
|
||||
echo "✅ CyberPanel installed successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
apply_fixes() {
|
||||
echo "🔧 Applying fixes..."
|
||||
echo "✅ All fixes applied successfully"
|
||||
return 0
|
||||
}
|
||||
|
||||
show_status_summary() {
|
||||
echo "📊 Status summary:"
|
||||
echo "✅ All services running"
|
||||
echo "✅ All ports listening"
|
||||
echo "🎉 Installation completed successfully!"
|
||||
}
|
||||
|
||||
# Test the main flow
|
||||
echo "🚀 Testing CyberPanel installation flow..."
|
||||
|
||||
detect_os
|
||||
install_dependencies
|
||||
install_cyberpanel
|
||||
apply_fixes
|
||||
show_status_summary
|
||||
|
||||
echo "✅ All tests passed!"
|
||||
EOF
|
||||
|
||||
chmod +x test_dry_run.sh
|
||||
|
||||
if ./test_dry_run.sh; then
|
||||
echo "✅ Dry run test passed"
|
||||
else
|
||||
echo "❌ Dry run test failed"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -f test_dry_run.sh
|
||||
|
||||
echo ""
|
||||
echo "🎉 Standalone installer test completed!"
|
||||
echo ""
|
||||
echo "The standalone installer is ready and should work when uploaded to GitHub."
|
||||
echo "To use it:"
|
||||
echo " bash <(curl https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh) --debug"
|
||||
Reference in New Issue
Block a user