mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-11-11 07:46:10 +01:00
bug fix: csf issue
This commit is contained in:
@@ -127,8 +127,38 @@ class secMiddleware:
|
|||||||
logging.writeToFile(f'Value being scanned {str(value)}')
|
logging.writeToFile(f'Value being scanned {str(value)}')
|
||||||
|
|
||||||
# Skip validation for ports key to allow port ranges with colons
|
# Skip validation for ports key to allow port ranges with colons
|
||||||
if key == 'ports':
|
# but only for CSF modifyPorts endpoint
|
||||||
|
if key == 'ports' and pathActual == '/firewall/modifyPorts':
|
||||||
|
# Validate that ports only contain numbers, commas, and colons
|
||||||
|
if type(value) == str:
|
||||||
|
import re
|
||||||
|
# Allow only: digits, commas, colons, and whitespace
|
||||||
|
if re.match(r'^[\d,:,\s]+$', value):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logging.writeToFile(f"Invalid port format in CSF configuration: {value}")
|
||||||
|
final_dic = {
|
||||||
|
'error_message': "Invalid port format. Only numbers, commas, and colons are allowed for port ranges.",
|
||||||
|
"errorMessage": "Invalid port format. Only numbers, commas, and colons are allowed for port ranges."}
|
||||||
|
final_json = json.dumps(final_dic)
|
||||||
|
return HttpResponse(final_json)
|
||||||
continue
|
continue
|
||||||
|
elif key == 'ports':
|
||||||
|
# For other endpoints, ports key continues to skip validation
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Allow protocol parameter for CSF modifyPorts endpoint
|
||||||
|
if key == 'protocol' and pathActual == '/firewall/modifyPorts':
|
||||||
|
# Validate protocol values
|
||||||
|
if value in ['TCP_IN', 'TCP_OUT', 'UDP_IN', 'UDP_OUT']:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logging.writeToFile(f"Invalid protocol in CSF configuration: {value}")
|
||||||
|
final_dic = {
|
||||||
|
'error_message': "Invalid protocol. Only TCP_IN, TCP_OUT, UDP_IN, UDP_OUT are allowed.",
|
||||||
|
"errorMessage": "Invalid protocol. Only TCP_IN, TCP_OUT, UDP_IN, UDP_OUT are allowed."}
|
||||||
|
final_json = json.dumps(final_dic)
|
||||||
|
return HttpResponse(final_json)
|
||||||
|
|
||||||
if type(value) == str or type(value) == bytes:
|
if type(value) == str or type(value) == bytes:
|
||||||
pass
|
pass
|
||||||
|
|||||||
129
REFACTORING_NOTES.md
Normal file
129
REFACTORING_NOTES.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# CyberPanel Installation Scripts Refactoring
|
||||||
|
|
||||||
|
## Date: January 5, 2025
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This document outlines the refactoring work performed on CyberPanel's installation scripts to consolidate common functionality and improve code maintainability.
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
- `/install/install.py`
|
||||||
|
- `/install/installCyberPanel.py`
|
||||||
|
- `/install/install_utils.py` (newly created)
|
||||||
|
|
||||||
|
## Refactoring Summary
|
||||||
|
|
||||||
|
### 1. Created Shared Utility Module
|
||||||
|
Created `install_utils.py` in the `/install/` directory to house common functions used by both `install.py` and `installCyberPanel.py`.
|
||||||
|
|
||||||
|
### 2. Functions Moved to install_utils.py
|
||||||
|
|
||||||
|
#### System Detection Functions
|
||||||
|
- **`FetchCloudLinuxAlmaVersionVersion()`**
|
||||||
|
- Detects CloudLinux and AlmaLinux versions
|
||||||
|
- Previously duplicated in both files with identical implementations
|
||||||
|
|
||||||
|
- **`get_Ubuntu_release()`**
|
||||||
|
- Gets Ubuntu release version from `/etc/lsb-release`
|
||||||
|
- Added parameters to handle minor differences between implementations
|
||||||
|
|
||||||
|
- **`get_distro()`**
|
||||||
|
- Detects Linux distribution (Ubuntu, CentOS, CentOS 8, OpenEuler)
|
||||||
|
- Only existed in `install.py`, now shared
|
||||||
|
|
||||||
|
#### Output and Logging
|
||||||
|
- **`stdOut(message, log=0, do_exit=0, code=os.EX_OK)`**
|
||||||
|
- Standard output function with timestamps
|
||||||
|
- **Enhanced with color support**:
|
||||||
|
- 🔴 Red: Errors, failures, critical issues
|
||||||
|
- 🟡 Yellow: Warnings and alerts
|
||||||
|
- 🟢 Green: Success messages
|
||||||
|
- 🔵 Blue: Running/processing operations
|
||||||
|
- 🟣 Purple: Default/general messages
|
||||||
|
- Colors automatically disabled when output is piped
|
||||||
|
|
||||||
|
#### Package Management
|
||||||
|
- **`get_package_install_command(distro, package_name, options="")`**
|
||||||
|
- Returns appropriate install command for the distribution
|
||||||
|
- Handles apt-get, yum, and dnf package managers
|
||||||
|
|
||||||
|
- **`get_package_remove_command(distro, package_name)`**
|
||||||
|
- Returns appropriate remove command for the distribution
|
||||||
|
|
||||||
|
#### Command Execution
|
||||||
|
- **`resFailed(distro, res)`**
|
||||||
|
- Checks if command execution failed based on return code
|
||||||
|
|
||||||
|
- **`call(command, distro, bracket, message, log=0, do_exit=0, code=os.EX_OK, shell=False)`**
|
||||||
|
- Executes shell commands with retry logic (3 attempts)
|
||||||
|
- Provides consistent error handling and logging
|
||||||
|
|
||||||
|
#### Password Generation
|
||||||
|
- **`char_set`** dictionary
|
||||||
|
- Character sets for password generation (kept for backward compatibility)
|
||||||
|
|
||||||
|
- **`generate_pass(length=14)`**
|
||||||
|
- Generates cryptographically secure passwords
|
||||||
|
- Uses `secrets` module instead of `random` for better security
|
||||||
|
|
||||||
|
- **`generate_random_string(length=32, include_special=False)`**
|
||||||
|
- Flexible string generation with optional special characters
|
||||||
|
|
||||||
|
#### LiteSpeed Management
|
||||||
|
- **`format_restart_litespeed_command(server_root_path)`**
|
||||||
|
- Formats the LiteSpeed restart command
|
||||||
|
|
||||||
|
### 3. Distribution Constants
|
||||||
|
Moved distribution constants to `install_utils.py`:
|
||||||
|
```python
|
||||||
|
ubuntu = 0
|
||||||
|
centos = 1
|
||||||
|
cent8 = 2
|
||||||
|
openeuler = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Key Improvements
|
||||||
|
|
||||||
|
#### Security Enhancements
|
||||||
|
- Password generation now uses `secrets` module for cryptographic security
|
||||||
|
- Removed usage of `random.choice()` for password generation
|
||||||
|
|
||||||
|
#### Code Quality
|
||||||
|
- Eliminated code duplication across files
|
||||||
|
- Single source of truth for common functionality
|
||||||
|
- Consistent error handling and logging
|
||||||
|
|
||||||
|
#### Maintainability
|
||||||
|
- Centralized utility functions in one location
|
||||||
|
- Easier to update and maintain shared functionality
|
||||||
|
- Better organization of code
|
||||||
|
|
||||||
|
#### Visual Improvements
|
||||||
|
- Added color-coded output for better readability
|
||||||
|
- Automatic detection of terminal capabilities
|
||||||
|
- Clear visual distinction between error, warning, success, and info messages
|
||||||
|
|
||||||
|
### 5. Backward Compatibility
|
||||||
|
All changes maintain backward compatibility:
|
||||||
|
- Function signatures preserved where possible
|
||||||
|
- Wrapper functions created in original locations when needed
|
||||||
|
- `installCyberPanel.py` continues to use `install.preFlightsChecks.call` through import
|
||||||
|
|
||||||
|
### 6. Testing
|
||||||
|
Created test scripts to verify functionality:
|
||||||
|
- Color output testing
|
||||||
|
- Password generation verification
|
||||||
|
- Ensured all functions work as expected
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
1. **Reduced Code Duplication**: Common functions now exist in single location
|
||||||
|
2. **Improved Security**: Cryptographically secure password generation
|
||||||
|
3. **Better User Experience**: Color-coded output for easier reading
|
||||||
|
4. **Easier Maintenance**: Changes to common functions only need to be made once
|
||||||
|
5. **Consistent Behavior**: Both installation scripts now use identical implementations
|
||||||
|
|
||||||
|
## Future Recommendations
|
||||||
|
1. Consider moving more shared functionality to `install_utils.py`
|
||||||
|
2. Add unit tests for utility functions
|
||||||
|
3. Consider creating additional utility modules for specific domains (e.g., `network_utils.py`, `database_utils.py`)
|
||||||
|
4. Document function parameters and return values more thoroughly
|
||||||
|
5. Consider adding configuration file support for installation parameters
|
||||||
@@ -701,7 +701,8 @@ context /.well-known/acme-challenge {
|
|||||||
|
|
||||||
command = acmePath + " --issue" + domain_list \
|
command = acmePath + " --issue" + domain_list \
|
||||||
+ ' --cert-file ' + existingCertPath + '/cert.pem' + ' --key-file ' + existingCertPath + '/privkey.pem' \
|
+ ' --cert-file ' + existingCertPath + '/cert.pem' + ' --key-file ' + existingCertPath + '/privkey.pem' \
|
||||||
+ ' --fullchain-file ' + existingCertPath + '/fullchain.pem' + ' -w /usr/local/lsws/Example/html -k ec-256 --force --staging'
|
+ ' --fullchain-file ' + existingCertPath + '/fullchain.pem' + ' -w /usr/local/lsws/Example/html -k ec-256 --force --staging' \
|
||||||
|
+ ' --webroot-path /usr/local/lsws/Example/html'
|
||||||
|
|
||||||
if ProcessUtilities.decideServer() == ProcessUtilities.OLS:
|
if ProcessUtilities.decideServer() == ProcessUtilities.OLS:
|
||||||
result = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
result = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
||||||
@@ -711,7 +712,8 @@ context /.well-known/acme-challenge {
|
|||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
command = acmePath + " --issue" + domain_list \
|
command = acmePath + " --issue" + domain_list \
|
||||||
+ ' --cert-file ' + existingCertPath + '/cert.pem' + ' --key-file ' + existingCertPath + '/privkey.pem' \
|
+ ' --cert-file ' + existingCertPath + '/cert.pem' + ' --key-file ' + existingCertPath + '/privkey.pem' \
|
||||||
+ ' --fullchain-file ' + existingCertPath + '/fullchain.pem' + ' -w /usr/local/lsws/Example/html -k ec-256 --force --server letsencrypt'
|
+ ' --fullchain-file ' + existingCertPath + '/fullchain.pem' + ' -w /usr/local/lsws/Example/html -k ec-256 --force --server letsencrypt' \
|
||||||
|
+ ' --webroot-path /usr/local/lsws/Example/html'
|
||||||
|
|
||||||
result = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
result = subprocess.run(command, capture_output=True, universal_newlines=True, shell=True)
|
||||||
|
|
||||||
@@ -765,6 +767,34 @@ context /.well-known/acme-challenge {
|
|||||||
|
|
||||||
def issueSSLForDomain(domain, adminEmail, sslpath, aliasDomain=None):
|
def issueSSLForDomain(domain, adminEmail, sslpath, aliasDomain=None):
|
||||||
try:
|
try:
|
||||||
|
# Check if certificate already exists and try to renew it first
|
||||||
|
existingCertPath = '/etc/letsencrypt/live/' + domain + '/fullchain.pem'
|
||||||
|
if os.path.exists(existingCertPath):
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"Certificate exists for {domain}, attempting renewal...")
|
||||||
|
|
||||||
|
# Try to renew using acme.sh
|
||||||
|
acmePath = '/root/.acme.sh/acme.sh'
|
||||||
|
if os.path.exists(acmePath):
|
||||||
|
# First set the webroot path for the domain
|
||||||
|
command = f'{acmePath} --update-account --accountemail {adminEmail}'
|
||||||
|
subprocess.call(command, shell=True)
|
||||||
|
|
||||||
|
# Build domain list for renewal
|
||||||
|
renewal_domains = f'-d {domain}'
|
||||||
|
if sslUtilities.checkDNSRecords(f'www.{domain}'):
|
||||||
|
renewal_domains += f' -d www.{domain}'
|
||||||
|
|
||||||
|
# Try to renew with explicit webroot
|
||||||
|
command = f'{acmePath} --renew {renewal_domains} --webroot /usr/local/lsws/Example/html --force'
|
||||||
|
result = subprocess.run(command, capture_output=True, text=True, shell=True)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"Successfully renewed SSL for {domain}")
|
||||||
|
if sslUtilities.installSSLForDomain(domain, adminEmail) == 1:
|
||||||
|
return [1, "None"]
|
||||||
|
else:
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile(f"Renewal failed for {domain}, falling back to new issuance")
|
||||||
|
|
||||||
if sslUtilities.obtainSSLForADomain(domain, adminEmail, sslpath, aliasDomain) == 1:
|
if sslUtilities.obtainSSLForADomain(domain, adminEmail, sslpath, aliasDomain) == 1:
|
||||||
if sslUtilities.installSSLForDomain(domain, adminEmail) == 1:
|
if sslUtilities.installSSLForDomain(domain, adminEmail) == 1:
|
||||||
return [1, "None"]
|
return [1, "None"]
|
||||||
|
|||||||
Reference in New Issue
Block a user