Compare commits
7
Commits
v1.0.1
..
99be50ebc6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99be50ebc6 | ||
|
|
85f0d94805 | ||
|
|
1a18c4c079 | ||
|
|
a770e24f26 | ||
|
|
f7ebc6c0a1 | ||
|
|
86649f796d | ||
|
|
78fc2ac8c5 |
@@ -28,7 +28,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Verify Python Syntax
|
- name: Verify Python Syntax
|
||||||
run: |
|
run: |
|
||||||
python3 -m py_compile Server.py Win_Client.py Linux_Client.py package_dist.py upload_release.py test_pipeline.py tests/*.py
|
python3 -m py_compile src/Server.py src/Win_Client.py src/Linux_Client.py package_dist.py upload_release.py test_pipeline.py tests/*.py
|
||||||
|
|
||||||
- name: Run Component Unit Tests
|
- name: Run Component Unit Tests
|
||||||
run: |
|
run: |
|
||||||
@@ -40,10 +40,10 @@ jobs:
|
|||||||
rm -f server_config.json client_config.json logar_state.db client_state.json
|
rm -f server_config.json client_config.json logar_state.db client_state.json
|
||||||
|
|
||||||
# 1. Initialize server config and export client configuration
|
# 1. Initialize server config and export client configuration
|
||||||
python3 Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
python3 src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
||||||
|
|
||||||
# 2. Launch LOGAR server in the background
|
# 2. Launch LOGAR server in the background
|
||||||
python3 Server.py &
|
python3 src/Server.py &
|
||||||
SERVER_PID=$!
|
SERVER_PID=$!
|
||||||
echo "[*] Server launched in background with PID $SERVER_PID"
|
echo "[*] Server launched in background with PID $SERVER_PID"
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ graph TB
|
|||||||
- A cryptographically random authentication secret token (`auth_token`).
|
- A cryptographically random authentication secret token (`auth_token`).
|
||||||
- **Client Configuration Exporter**:
|
- **Client Configuration Exporter**:
|
||||||
```bash
|
```bash
|
||||||
python Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
python src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
||||||
```
|
```
|
||||||
Produces an anonymous client config containing only the server socket coordinates, authentication token, and the encryption-only public key & fingerprint.
|
Produces an anonymous client config containing only the server socket coordinates, authentication token, and the encryption-only public key & fingerprint.
|
||||||
- **Socket Protocol Framing**:
|
- **Socket Protocol Framing**:
|
||||||
@@ -180,9 +180,11 @@ LOGAR/
|
|||||||
├── .gitignore # Ignore venv, caches, DBs, and private keys
|
├── .gitignore # Ignore venv, caches, DBs, and private keys
|
||||||
├── requirements.txt # Unified dependencies
|
├── requirements.txt # Unified dependencies
|
||||||
├── README.md # Comprehensive documentation
|
├── README.md # Comprehensive documentation
|
||||||
├── Server.py # Central TCP server and Hermes API
|
├── src/ # Core application source modules
|
||||||
├── Win_Client.py # Windows edge forwarder
|
│ ├── __init__.py
|
||||||
├── Linux_Client.py # Linux edge forwarder
|
│ ├── Server.py # Central TCP server and Hermes API
|
||||||
|
│ ├── Win_Client.py # Windows edge forwarder
|
||||||
|
│ └── Linux_Client.py # Linux edge forwarder
|
||||||
├── server_config.sample.json # Central server sample configuration
|
├── server_config.sample.json # Central server sample configuration
|
||||||
├── package_dist.py # Multi-platform standalone binary packaging script
|
├── package_dist.py # Multi-platform standalone binary packaging script
|
||||||
├── upload_release.py # Direct Gitea REST API release asset publisher
|
├── upload_release.py # Direct Gitea REST API release asset publisher
|
||||||
@@ -212,11 +214,11 @@ LOGAR/
|
|||||||
```
|
```
|
||||||
2. **Start the server** (generates `server_config.json` and keypair on first run):
|
2. **Start the server** (generates `server_config.json` and keypair on first run):
|
||||||
```bash
|
```bash
|
||||||
python Server.py
|
python src/Server.py
|
||||||
```
|
```
|
||||||
3. **Export a client configuration**:
|
3. **Export a client configuration**:
|
||||||
```bash
|
```bash
|
||||||
python Server.py --create-client-config --server-host <SERVER_IP> --server-port 9443 --client-out client_config.json
|
python src/Server.py --create-client-config --server-host <SERVER_IP> --server-port 9443 --client-out client_config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Windows Client Deployment
|
### 2. Windows Client Deployment
|
||||||
@@ -287,11 +289,11 @@ The pipeline test exercises invalid token rejection, encrypted socket streaming,
|
|||||||
|
|
||||||
1. **Start the server** in Shell 1 (creates `server_config.json` on first run):
|
1. **Start the server** in Shell 1 (creates `server_config.json` on first run):
|
||||||
```bash
|
```bash
|
||||||
python Server.py
|
python src/Server.py
|
||||||
```
|
```
|
||||||
2. **Export client configuration** in Shell 2 (required for testing):
|
2. **Export client configuration** in Shell 2 (required for testing):
|
||||||
```bash
|
```bash
|
||||||
python Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
python src/Server.py --create-client-config --server-host 127.0.0.1 --server-port 9443 --client-out client_config.json
|
||||||
```
|
```
|
||||||
3. **Execute the integration test** in Shell 2:
|
3. **Execute the integration test** in Shell 2:
|
||||||
```bash
|
```bash
|
||||||
@@ -301,7 +303,7 @@ The pipeline test exercises invalid token rejection, encrypted socket streaming,
|
|||||||
## Continuous Integration via Gitea Actions
|
## Continuous Integration via Gitea Actions
|
||||||
|
|
||||||
Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request:
|
Continuous integration is automated via [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml) and triggers automatically on **every push** and pull request:
|
||||||
1. **Syntax Compilation**: Validates all Python scripts (`Server.py`, `Win_Client.py`, `Linux_Client.py`, `package_dist.py`, `upload_release.py`, `test_pipeline.py`, and test suites).
|
1. **Syntax Compilation**: Validates all Python scripts (`src/Server.py`, `src/Win_Client.py`, `src/Linux_Client.py`, `package_dist.py`, `upload_release.py`, `test_pipeline.py`, and test suites).
|
||||||
2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`).
|
2. **Component Unit Tests**: Discovers and runs all unit tests in `tests/` (`test_server.py`, `test_win_client.py`, `test_linux_client.py`).
|
||||||
3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance.
|
3. **End-to-End Pipeline Verification**: Automatically spins up the LOGAR server hub, generates test configs, runs `test_pipeline.py` (testing socket authentication, 4-run rule persistence, Hermes API report, and client integrations), and shuts down the test instance.
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Standalone compiled binary distribution for Linux edge servers running systemd.
|
|||||||
Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
|
Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
|
python src/Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
|
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Standalone compiled executable distribution for Windows Server and workstation e
|
|||||||
Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
|
Run the following command on your central LOGAR server to export a client bundle tailored for your environment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
|
python src/Server.py --create-client-config --server-host <SERVER_IP_OR_DNS> --server-port 9443 --client-out client_config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
|
- Replace `<SERVER_IP_OR_DNS>` with the reachable IP address or FQDN of your central LOGAR server hub.
|
||||||
|
|||||||
+7
-6
@@ -8,6 +8,7 @@ import subprocess
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||||
DIST_DIR = os.path.abspath("dist")
|
DIST_DIR = os.path.abspath("dist")
|
||||||
BUILD_TEMP = os.path.abspath("build_temp")
|
BUILD_TEMP = os.path.abspath("build_temp")
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ def build_linux_zipapp_fallback():
|
|||||||
# Linux Client zipapp
|
# Linux Client zipapp
|
||||||
app_dir = os.path.join(BUILD_TEMP, "linux_app")
|
app_dir = os.path.join(BUILD_TEMP, "linux_app")
|
||||||
os.makedirs(app_dir, exist_ok=True)
|
os.makedirs(app_dir, exist_ok=True)
|
||||||
shutil.copy(os.path.join(ROOT_DIR, "Linux_Client.py"), os.path.join(app_dir, "Linux_Client.py"))
|
shutil.copy(os.path.join(SRC_DIR, "Linux_Client.py"), os.path.join(app_dir, "Linux_Client.py"))
|
||||||
client_out = os.path.join(DIST_DIR, "Linux_Client.bin")
|
client_out = os.path.join(DIST_DIR, "Linux_Client.bin")
|
||||||
zipapp.create_archive(
|
zipapp.create_archive(
|
||||||
source=app_dir,
|
source=app_dir,
|
||||||
@@ -66,7 +67,7 @@ def build_linux_zipapp_fallback():
|
|||||||
# Server zipapp
|
# Server zipapp
|
||||||
srv_dir = os.path.join(BUILD_TEMP, "linux_srv")
|
srv_dir = os.path.join(BUILD_TEMP, "linux_srv")
|
||||||
os.makedirs(srv_dir, exist_ok=True)
|
os.makedirs(srv_dir, exist_ok=True)
|
||||||
shutil.copy(os.path.join(ROOT_DIR, "Server.py"), os.path.join(srv_dir, "Server.py"))
|
shutil.copy(os.path.join(SRC_DIR, "Server.py"), os.path.join(srv_dir, "Server.py"))
|
||||||
server_out = os.path.join(DIST_DIR, "Server.bin")
|
server_out = os.path.join(DIST_DIR, "Server.bin")
|
||||||
zipapp.create_archive(
|
zipapp.create_archive(
|
||||||
source=srv_dir,
|
source=srv_dir,
|
||||||
@@ -77,10 +78,10 @@ def build_linux_zipapp_fallback():
|
|||||||
|
|
||||||
def build_windows():
|
def build_windows():
|
||||||
print("[*] Compiling Windows standalone executables...")
|
print("[*] Compiling Windows standalone executables...")
|
||||||
win_client_script = os.path.join(ROOT_DIR, "Win_Client.py")
|
win_client_script = os.path.join(SRC_DIR, "Win_Client.py")
|
||||||
build_pyinstaller_binary(win_client_script, "Win_Client")
|
build_pyinstaller_binary(win_client_script, "Win_Client")
|
||||||
|
|
||||||
server_script = os.path.join(ROOT_DIR, "Server.py")
|
server_script = os.path.join(SRC_DIR, "Server.py")
|
||||||
build_pyinstaller_binary(server_script, "Server")
|
build_pyinstaller_binary(server_script, "Server")
|
||||||
|
|
||||||
client_bin = os.path.join(DIST_DIR, "Win_Client.exe")
|
client_bin = os.path.join(DIST_DIR, "Win_Client.exe")
|
||||||
@@ -111,10 +112,10 @@ def build_linux():
|
|||||||
is_linux_host = platform.system() == "Linux"
|
is_linux_host = platform.system() == "Linux"
|
||||||
|
|
||||||
if is_linux_host:
|
if is_linux_host:
|
||||||
linux_client_script = os.path.join(ROOT_DIR, "Linux_Client.py")
|
linux_client_script = os.path.join(SRC_DIR, "Linux_Client.py")
|
||||||
build_pyinstaller_binary(linux_client_script, "Linux_Client.bin")
|
build_pyinstaller_binary(linux_client_script, "Linux_Client.bin")
|
||||||
|
|
||||||
server_script = os.path.join(ROOT_DIR, "Server.py")
|
server_script = os.path.join(SRC_DIR, "Server.py")
|
||||||
build_pyinstaller_binary(server_script, "Server.bin")
|
build_pyinstaller_binary(server_script, "Server.bin")
|
||||||
|
|
||||||
# Normalize extensions in case PyInstaller dropped .bin
|
# Normalize extensions in case PyInstaller dropped .bin
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import urllib.request
|
|||||||
import warnings
|
import warnings
|
||||||
from datetime import datetime, timezone, timedelta
|
from datetime import datetime, timezone, timedelta
|
||||||
|
|
||||||
|
# Ensure src/ directory is in sys.path
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "src")))
|
||||||
|
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
import pgpy
|
import pgpy
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import warnings
|
|||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
||||||
|
|
||||||
import Linux_Client
|
import Linux_Client
|
||||||
import pgpy
|
import pgpy
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ from datetime import datetime, timezone, timedelta
|
|||||||
|
|
||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
# Ensure parent directory is in path to import Server
|
# Ensure parent directory and src directory are in path to import Server
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
||||||
|
|
||||||
import Server
|
import Server
|
||||||
import pgpy
|
import pgpy
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import warnings
|
|||||||
warnings.filterwarnings("ignore")
|
warnings.filterwarnings("ignore")
|
||||||
|
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
||||||
|
|
||||||
import Win_Client
|
import Win_Client
|
||||||
import pgpy
|
import pgpy
|
||||||
|
|||||||
Reference in New Issue
Block a user