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)}')
|
||||
|
||||
# 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
|
||||
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:
|
||||
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 \
|
||||
+ ' --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:
|
||||
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:
|
||||
command = acmePath + " --issue" + domain_list \
|
||||
+ ' --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)
|
||||
|
||||
@@ -765,6 +767,34 @@ context /.well-known/acme-challenge {
|
||||
|
||||
def issueSSLForDomain(domain, adminEmail, sslpath, aliasDomain=None):
|
||||
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.installSSLForDomain(domain, adminEmail) == 1:
|
||||
return [1, "None"]
|
||||
|
||||
Reference in New Issue
Block a user