🔃 Sync Hub v0.4

This commit is contained in:
jokob-sk
2024-06-04 17:36:10 +10:00
parent 46e7e7bc01
commit 02eafadf15
7 changed files with 80 additions and 16 deletions

View File

@@ -13,7 +13,7 @@ ENV PATH="/opt/venv/bin:$PATH"
COPY . ${INSTALL_DIR}/ COPY . ${INSTALL_DIR}/
RUN pip install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython \ RUN pip install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython pycryptodome \
&& bash -c "find ${INSTALL_DIR} -type d -exec chmod 750 {} \;" \ && bash -c "find ${INSTALL_DIR} -type d -exec chmod 750 {} \;" \
&& bash -c "find ${INSTALL_DIR} -type f -exec chmod 640 {} \;" \ && bash -c "find ${INSTALL_DIR} -type f -exec chmod 640 {} \;" \
&& bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;" && bash -c "find ${INSTALL_DIR} -type f \( -name '*.sh' -o -name '*.py' -o -name 'speedtest-cli' \) -exec chmod 750 {} \;"

View File

@@ -42,7 +42,7 @@ RUN phpenmod -v 8.2 sqlite3
RUN apt-get install -y python3-venv RUN apt-get install -y python3-venv
RUN python3 -m venv myenv RUN python3 -m venv myenv
RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython" RUN /bin/bash -c "source myenv/bin/activate && update-alternatives --install /usr/bin/python python /usr/bin/python3 10 && pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython pycryptodome"
# Create a buildtimestamp.txt to later check if a new version was released # Create a buildtimestamp.txt to later check if a new version was released
RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt

View File

@@ -432,6 +432,26 @@
} }
] ]
}, },
{
"function": "encryption_key",
"type": "text",
"maxLength": 50,
"default_value": "",
"options": [],
"localized": ["name", "description"],
"name": [
{
"language_code": "en_us",
"string": "Encryption Key"
}
],
"description": [
{
"language_code": "en_us",
"string": "Encryption key used to encrypt the sent data. The key needs to be the same on the hub and on the nodes."
}
]
},
{ {
"function": "CMD", "function": "CMD",
"type": "readonly", "type": "readonly",

View File

@@ -3,6 +3,30 @@
// External files // External files
require '/app/front/php/server/init.php'; require '/app/front/php/server/init.php';
function decrypt_data($encoded_data) {
// Base64 decode the encoded data
$decoded_data = base64_decode($encoded_data);
// Extract the initialization vector (IV) from the decoded data
$iv = substr($decoded_data, 0, 16);
// Extract the actual encrypted data
$encrypted_data = substr($decoded_data, 16);
// Get the encryption key from the settings
$key = hash('sha256', getSettingValue('SYNC_encryption_key'), true);
// Decrypt the data
$decrypted_data = openssl_decrypt($encrypted_data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
if ($decrypted_data === false) {
return null; // Decryption failed
}
return $decrypted_data;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Retrieve the authorization header // Retrieve the authorization header
$headers = apache_request_headers(); $headers = apache_request_headers();
@@ -22,7 +46,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$plugin_folder = $_POST['plugin_folder'] ?? ''; $plugin_folder = $_POST['plugin_folder'] ?? '';
$node_name = $_POST['node_name'] ?? ''; $node_name = $_POST['node_name'] ?? '';
$decoded_data = hex2bin($data); $decoded_data = decrypt_data($data);
if ($decrypted_data === false or $decrypted_data === null) {
write_notification("[Plugin: Sync hub API] Bad Request: Decryption failed", "alert");
http_response_code(400);
echo 'Bad Request: Decryption failed';
exit;
}
$storage_path = "/app/front/plugins/{$plugin_folder}"; $storage_path = "/app/front/plugins/{$plugin_folder}";
// Create the storage directory if it doesn't exist // Create the storage directory if it doesn't exist

View File

@@ -14,7 +14,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64 from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
from plugin_utils import get_plugins_configs from plugin_utils import get_plugins_configs
from logger import mylog from logger import mylog
from helper import timeNowTZ, get_setting_value from helper import timeNowTZ, get_setting_value, encrypt_data
# Define the current path and log file paths # Define the current path and log file paths
CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
@@ -23,12 +23,6 @@ RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
pluginName = 'SYNC' pluginName = 'SYNC'
# Function to encrypt data using a password
def encrypt_data(data, password):
key = hashlib.sha256(password.encode()).digest()
cipher = hashlib.pbkdf2_hmac('sha256', data.encode(), key, 100000)
return cipher.hex()
def main(): def main():
mylog('verbose', [f'[{pluginName}] In script']) mylog('verbose', [f'[{pluginName}] In script'])
@@ -38,7 +32,8 @@ def main():
# Retrieve configuration settings # Retrieve configuration settings
plugins_to_sync = get_setting_value('SYNC_plugins') plugins_to_sync = get_setting_value('SYNC_plugins')
api_token = get_setting_value('SYNC_api_token') # Use an API token instead of a password api_token = get_setting_value('SYNC_api_token')
encryption_key = get_setting_value('SYNC_encryption_key')
hub_url = get_setting_value('SYNC_hub_url') hub_url = get_setting_value('SYNC_hub_url')
node_name = get_setting_value('SYNC_node_name') node_name = get_setting_value('SYNC_node_name')
@@ -63,9 +58,14 @@ def main():
if os.path.exists(file_path): if os.path.exists(file_path):
# Read the content of the log file # Read the content of the log file
with open(file_path, 'r') as f: with open(file_path, 'r') as f:
newLines = f.read() file_content = f.read()
# Encrypt the log data using the API token
encrypted_data = encrypt_data(newLines, api_token) mylog('verbose', [f'[{pluginName}] Sending file_content: "{file_content}"'])
# Encrypt the log data using the encryption_key
encrypted_data = encrypt_data(file_content, encryption_key)
mylog('verbose', [f'[{pluginName}] Sending encrypted_data: "{encrypted_data}"'])
# Prepare the data payload for the POST request # Prepare the data payload for the POST request
data = { data = {
@@ -84,7 +84,7 @@ def main():
if response.status_code == 200: if response.status_code == 200:
mylog('verbose', [f'[{pluginName}] Data for "{plugin_folder}" sent successfully']) mylog('verbose', [f'[{pluginName}] Data for "{plugin_folder}" sent successfully'])
else: else:
mylog('error', [f'[{pluginName}] Failed to send data for "{plugin_folder}"']) mylog('verbose', [f'[{pluginName}] Failed to send data for "{plugin_folder}"'])
# log result # log result
plugin_objects.add_object( plugin_objects.add_object(

View File

@@ -30,5 +30,5 @@ source myenv/bin/activate
update-alternatives --install /usr/bin/python python /usr/bin/python3 10 update-alternatives --install /usr/bin/python python /usr/bin/python3 10
# install packages thru pip3 # install packages thru pip3
pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi speedtest-cli chardet python-nmap dnspython pycryptodome

View File

@@ -13,6 +13,11 @@ import json
import time import time
from pathlib import Path from pathlib import Path
import requests import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
import hashlib
import conf import conf
from const import * from const import *
@@ -798,6 +803,13 @@ def collect_lang_strings(json, pref, stringSqlParams):
return stringSqlParams return stringSqlParams
def encrypt_data(data, key):
key = hashlib.sha256(key.encode()).digest() # Ensure the key is 32 bytes long
cipher = AES.new(key, AES.MODE_CBC) # Use CBC mode for encryption
iv = cipher.iv # Initialization vector
encrypted_data = cipher.encrypt(pad(data.encode(), AES.block_size))
return base64.b64encode(iv + encrypted_data).decode('utf-8')
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Misc # Misc
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------