diff --git a/data/.env b/data/.env new file mode 100644 index 0000000..d9b922e --- /dev/null +++ b/data/.env @@ -0,0 +1,8 @@ +WALLET_MASTER_PASSWORD=Ase#2024@wallet! +DB_NAME=postgres +DB_SCHEMA=mqtt_sec +DB_TABLE=passwords +DB_USER=postgres +DB_PASSWORD=BatManu#171017@mqtt! +DB_HOST=localhost +DB_PORT=5432 diff --git a/password_wallet_api.py b/password_wallet_api.py index 1aa23dd..d794137 100644 --- a/password_wallet_api.py +++ b/password_wallet_api.py @@ -1,6 +1,6 @@ from flask import Flask, request, jsonify import os -import sqlite3 +import psycopg2 import bcrypt import base64 import hashlib @@ -9,20 +9,40 @@ from cryptography.fernet import Fernet from waitress import serve # Configurazione -db_file = "data/passwords.db" hash_file = "data/master_hash.txt" + +# Configurazione connessione PostgreSQL +DB_CONFIG = { + "dbname": os.getenv("DB_NAME"), + "dbschema": os.getenv("DB_SCHEMA"), + "dbtable": os.getenv("DB_TABLE"), + "user": os.getenv("DB_USER"), + "password": os.getenv("DB_PASSWORD"), + "host": os.getenv("DB_HOST"), + "port": os.getenv("DB_PORT") +} app = Flask(__name__) # Configura il logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - PID: %(process)d %(levelname)s - %(message)s') +def get_db_connection(): + return psycopg2.connect( + dbname=DB_CONFIG["dbname"], + user=DB_CONFIG["user"], + password=DB_CONFIG["password"], + host=DB_CONFIG["host"], + port=DB_CONFIG["port"] + ) + + # Inizializza il database def init_db(): - conn = sqlite3.connect(db_file) + conn = get_db_connection() cursor = conn.cursor() - cursor.execute(""" - CREATE TABLE IF NOT EXISTS passwords ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + cursor.execute(f""" + CREATE TABLE IF NOT EXISTS {DB_CONFIG['dbschema']}.{DB_CONFIG['dbtable']} ( + id SERIAL PRIMARY KEY, site TEXT NOT NULL, username TEXT NOT NULL, password TEXT NOT NULL @@ -69,25 +89,26 @@ def authenticate(master_password): # Aggiungi una password al database def add_password(site, username, password, cipher): - conn = sqlite3.connect(db_file) + conn = get_db_connection() cursor = conn.cursor() encrypted_password = cipher.encrypt(password.encode()).decode() try: - cursor.execute("INSERT INTO passwords (site, username, password) VALUES (?, ?, ?)", - (site, username, encrypted_password)) + cursor.execute( + f"INSERT INTO {DB_CONFIG['dbschema']}.{DB_CONFIG['dbtable']} (site, username, password) VALUES (%s, %s, %s)", + (site, username, encrypted_password)) conn.commit() logging.info(f"Password aggiunta per il sito: {site}.") - except sqlite3.Error as e: + except psycopg2.Error as e: logging.error(f"Errore durante l'aggiunta della password: {e}") finally: conn.close() # Recupera una password dal database def get_password(site, cipher): - conn = sqlite3.connect(db_file) + conn = get_db_connection() cursor = conn.cursor() try: - cursor.execute("SELECT username, password FROM passwords WHERE site = ?", (site,)) + cursor.execute(f"SELECT username, password FROM {DB_CONFIG['dbschema']}.{DB_CONFIG['dbtable']} WHERE site = %s", (site,)) row = cursor.fetchone() if row: username, encrypted_password = row @@ -96,7 +117,7 @@ def get_password(site, cipher): return username, decrypted_password logging.warning(f"Sito non trovato: {site}.") return None, None - except sqlite3.Error as e: + except psycopg2.Error as e: logging.error(f"Errore durante il recupero della password: {e}") return None, None finally: @@ -104,30 +125,30 @@ def get_password(site, cipher): # Cancella una password dal database def delete_password(site): - conn = sqlite3.connect(db_file) + conn = get_db_connection() cursor = conn.cursor() try: - cursor.execute("DELETE FROM passwords WHERE site = ?", (site,)) + cursor.execute(f"DELETE FROM {DB_CONFIG['dbschema']}.{DB_CONFIG['dbtable']} WHERE site = %s", (site,)) if cursor.rowcount > 0: logging.info(f"Password cancellata per il sito: {site}.") else: logging.warning(f"Nessuna password trovata per il sito: {site}.") conn.commit() - except sqlite3.Error as e: + except psycopg2.Error as e: logging.error(f"Errore durante la cancellazione della password: {e}") finally: conn.close() # Ottieni la lista di tutti i siti def list_sites(): - conn = sqlite3.connect(db_file) + conn = get_db_connection() cursor = conn.cursor() try: - cursor.execute("SELECT site FROM passwords") + cursor.execute(f"SELECT site FROM {DB_CONFIG['dbschema']}.{DB_CONFIG['dbtable']}") sites = [row[0] for row in cursor.fetchall()] logging.info("Elenco dei siti recuperato.") return sites - except sqlite3.Error as e: + except psycopg2.Error as e: logging.error(f"Errore durante il recupero dell'elenco dei siti: {e}") return [] finally: diff --git a/pyproject.toml b/pyproject.toml index 5b84261..510c4cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "cryptography>=44.0.0", "flask>=3.1.0", "paho-mqtt>=2.1.0", + "psycopg2-binary>=2.9.10", "requests>=2.32.3", "waitress>=3.0.2", ] diff --git a/services/control_mqtt.conf b/services/control_mqtt.conf new file mode 100644 index 0000000..7040982 --- /dev/null +++ b/services/control_mqtt.conf @@ -0,0 +1,2 @@ +if $programname == 'control_mqtt' then /var/log/mqtt_ase/subscriber_manager.log +& stop diff --git a/services/password_wallet.conf b/services/password_wallet.conf new file mode 100644 index 0000000..1da150c --- /dev/null +++ b/services/password_wallet.conf @@ -0,0 +1,2 @@ +if $programname == 'password_wallet' then /var/log/mqtt_ase/password_wallet.log +& stop diff --git a/services/password_wallet.service b/services/password_wallet.service index 74b4c51..b8e7dce 100644 --- a/services/password_wallet.service +++ b/services/password_wallet.service @@ -6,6 +6,7 @@ After=network.target User=mosquitto WorkingDirectory=/var/lib/mosquitto ExecStart=/var/lib/mosquitto/.venv/bin/python3 /var/lib/mosquitto/password_wallet_api.py +EnvironmentFile=/var/lib/mosquitto/data/.env Restart=always SyslogIdentifier=password_wallet diff --git a/uv.lock b/uv.lock index 176a92e..416cec7 100644 --- a/uv.lock +++ b/uv.lock @@ -10,6 +10,7 @@ dependencies = [ { name = "cryptography" }, { name = "flask" }, { name = "paho-mqtt" }, + { name = "psycopg2-binary" }, { name = "requests" }, { name = "waitress" }, ] @@ -20,6 +21,7 @@ requires-dist = [ { name = "cryptography", specifier = ">=44.0.0" }, { name = "flask", specifier = ">=3.1.0" }, { name = "paho-mqtt", specifier = ">=2.1.0" }, + { name = "psycopg2-binary", specifier = ">=2.9.10" }, { name = "requests", specifier = ">=2.32.3" }, { name = "waitress", specifier = ">=3.0.2" }, ] @@ -289,6 +291,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219 }, ] +[[package]] +name = "psycopg2-binary" +version = "2.9.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/bdc8274dc0585090b4e3432267d7be4dfbfd8971c0fa59167c711105a6bf/psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2", size = 385764 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/7d/465cc9795cf76f6d329efdafca74693714556ea3891813701ac1fee87545/psycopg2_binary-2.9.10-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0", size = 3044771 }, + { url = "https://files.pythonhosted.org/packages/8b/31/6d225b7b641a1a2148e3ed65e1aa74fc86ba3fee850545e27be9e1de893d/psycopg2_binary-2.9.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a", size = 3275336 }, + { url = "https://files.pythonhosted.org/packages/30/b7/a68c2b4bff1cbb1728e3ec864b2d92327c77ad52edcd27922535a8366f68/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539", size = 2851637 }, + { url = "https://files.pythonhosted.org/packages/0b/b1/cfedc0e0e6f9ad61f8657fd173b2f831ce261c02a08c0b09c652b127d813/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526", size = 3082097 }, + { url = "https://files.pythonhosted.org/packages/18/ed/0a8e4153c9b769f59c02fb5e7914f20f0b2483a19dae7bf2db54b743d0d0/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1", size = 3264776 }, + { url = "https://files.pythonhosted.org/packages/10/db/d09da68c6a0cdab41566b74e0a6068a425f077169bed0946559b7348ebe9/psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e", size = 3020968 }, + { url = "https://files.pythonhosted.org/packages/94/28/4d6f8c255f0dfffb410db2b3f9ac5218d959a66c715c34cac31081e19b95/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f", size = 2872334 }, + { url = "https://files.pythonhosted.org/packages/05/f7/20d7bf796593c4fea95e12119d6cc384ff1f6141a24fbb7df5a668d29d29/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00", size = 2822722 }, + { url = "https://files.pythonhosted.org/packages/4d/e4/0c407ae919ef626dbdb32835a03b6737013c3cc7240169843965cada2bdf/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5", size = 2920132 }, + { url = "https://files.pythonhosted.org/packages/2d/70/aa69c9f69cf09a01da224909ff6ce8b68faeef476f00f7ec377e8f03be70/psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47", size = 2959312 }, + { url = "https://files.pythonhosted.org/packages/d3/bd/213e59854fafe87ba47814bf413ace0dcee33a89c8c8c814faca6bc7cf3c/psycopg2_binary-2.9.10-cp312-cp312-win32.whl", hash = "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64", size = 1025191 }, + { url = "https://files.pythonhosted.org/packages/92/29/06261ea000e2dc1e22907dbbc483a1093665509ea586b29b8986a0e56733/psycopg2_binary-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0", size = 1164031 }, + { url = "https://files.pythonhosted.org/packages/3e/30/d41d3ba765609c0763505d565c4d12d8f3c79793f0d0f044ff5a28bf395b/psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d", size = 3044699 }, + { url = "https://files.pythonhosted.org/packages/35/44/257ddadec7ef04536ba71af6bc6a75ec05c5343004a7ec93006bee66c0bc/psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb", size = 3275245 }, + { url = "https://files.pythonhosted.org/packages/1b/11/48ea1cd11de67f9efd7262085588790a95d9dfcd9b8a687d46caf7305c1a/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7", size = 2851631 }, + { url = "https://files.pythonhosted.org/packages/62/e0/62ce5ee650e6c86719d621a761fe4bc846ab9eff8c1f12b1ed5741bf1c9b/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d", size = 3082140 }, + { url = "https://files.pythonhosted.org/packages/27/ce/63f946c098611f7be234c0dd7cb1ad68b0b5744d34f68062bb3c5aa510c8/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73", size = 3264762 }, + { url = "https://files.pythonhosted.org/packages/43/25/c603cd81402e69edf7daa59b1602bd41eb9859e2824b8c0855d748366ac9/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673", size = 3020967 }, + { url = "https://files.pythonhosted.org/packages/5f/d6/8708d8c6fca531057fa170cdde8df870e8b6a9b136e82b361c65e42b841e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f", size = 2872326 }, + { url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712 }, + { url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155 }, + { url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356 }, +] + [[package]] name = "pycparser" version = "2.22"