Skip to content

Commit 572f198

Browse files
unique systemguard id added
1 parent ad40294 commit 572f198

File tree

8 files changed

+189
-14
lines changed

8 files changed

+189
-14
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,5 @@ prometheus_config/prometheus.yml
170170
prometheus_config/alertmanager.yml
171171
test.py
172172
.initialized
173+
174+
*.conf

setup_nginx.sh

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/bin/bash
2+
3+
# Step 1: Pull Nginx Docker image
4+
echo "Pulling Nginx Docker image..."
5+
docker pull nginx:latest
6+
HOST_IP=$(hostname -I | cut -d' ' -f1)
7+
SYSTEMGUARD_PORT=5001
8+
# STATIC_FOLDER=/path/to/static/folder
9+
10+
# Step 2: Create main Nginx configuration (nginx.conf)
11+
echo "Creating main Nginx configuration..."
12+
13+
cat > nginx.conf <<EOL
14+
worker_processes auto;
15+
pid /run/nginx.pid;
16+
17+
events {
18+
worker_connections 1024;
19+
}
20+
21+
http {
22+
# Define a log format for access logs
23+
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
24+
'\$status \$body_bytes_sent "\$http_referer" '
25+
'"\$http_user_agent" "\$http_x_forwarded_for"';
26+
27+
# Enable gzip compression
28+
gzip on;
29+
gzip_types text/plain application/json application/javascript text/css application/xml;
30+
gzip_min_length 256;
31+
gzip_vary on;
32+
33+
# Include all server configurations
34+
include /etc/nginx/conf.d/*.conf;
35+
}
36+
EOL
37+
38+
# Step 3: Create server configuration for Flask app (default.conf)
39+
echo "Creating server configuration..."
40+
41+
cat > default.conf <<EOL
42+
server {
43+
listen 80;
44+
45+
# Security headers
46+
add_header X-Frame-Options "SAMEORIGIN" always;
47+
add_header X-Content-Type-Options "nosniff" always;
48+
add_header X-XSS-Protection "1; mode=block" always;
49+
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains" always;
50+
add_header Referrer-Policy "no-referrer";
51+
52+
# Proxy to Flask app
53+
location / {
54+
proxy_pass http://$HOST_IP:$SYSTEMGUARD_PORT;
55+
proxy_set_header Host \$host;
56+
proxy_set_header X-Real-IP \$remote_addr;
57+
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
58+
proxy_set_header X-Forwarded-Proto \$scheme;
59+
60+
# Client timeout settings
61+
proxy_connect_timeout 60s;
62+
proxy_read_timeout 60s;
63+
proxy_send_timeout 60s;
64+
}
65+
66+
# Serve static files directly
67+
# location /static/ {
68+
# alias $STATIC_FOLDER;
69+
# expires -1; # Disable caching
70+
# add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
71+
# }
72+
73+
# Error pages
74+
error_page 500 502 503 504 /50x.html;
75+
location = /50x.html {
76+
root /usr/share/nginx/html;
77+
}
78+
79+
# Access and error log configuration
80+
access_log /var/log/nginx/access.log main;
81+
error_log /var/log/nginx/error.log warn;
82+
83+
# Limit body size to prevent large requests from overwhelming the server
84+
client_max_body_size 10M;
85+
86+
# Buffer settings to optimize performance
87+
client_body_buffer_size 128k;
88+
proxy_buffer_size 4k;
89+
proxy_buffers 16 16k;
90+
proxy_busy_buffers_size 64k;
91+
92+
# Deny access to sensitive files
93+
location ~ /\.ht {
94+
deny all;
95+
}
96+
}
97+
EOL
98+
99+
# Step 4: Start Nginx container with reverse proxy to Flask app
100+
echo "Starting Nginx container..."
101+
docker run -d --name nginx_proxy \
102+
-p 80:80 \
103+
-v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \
104+
-v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf \
105+
nginx:latest
106+
107+
echo "Nginx reverse proxy set up successfully!"

src/helper.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,19 @@ def check_installation_information():
8888
def load_secret_key():
8989
"""Load the secret key for the application."""
9090
load_dotenv()
91-
secret_key = os.getenv('SYSTEMGUARD_KEY')
92-
if secret_key:
93-
return secret_key
94-
else:
95-
try:
96-
with open('secret.key', 'rb') as key_file:
97-
secret_key = key_file.read()
98-
return secret_key
99-
except FileNotFoundError:
100-
raise FileNotFoundError("The secret key file 'secret.key' was not found.")
101-
except Exception as e:
102-
raise RuntimeError(f"An error occurred while reading the secret key: {e}")
91+
try:
92+
secret_key = os.getenv('SYSTEMGUARD_KEY')
93+
if secret_key:
94+
return secret_key
95+
else:
96+
try:
97+
with open('secret.key', 'rb') as key_file:
98+
secret_key = key_file.read()
99+
return secret_key
100+
except FileNotFoundError:
101+
raise FileNotFoundError("The secret key file 'secret.key' was not found.")
102+
except Exception as e:
103+
raise RuntimeError(f"An error occurred while reading the secret key: {e}")
104+
except Exception as e:
105+
# temporary fix
106+
return "1234567890123456"

src/routes/api.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def graph_data_api():
8282

8383
# Determine the start time based on the filter
8484
time_deltas = {
85+
'1 minute': 1 * 60,
8586
'5 minutes': 5 * 60,
8687
'15 minutes': 15 * 60,
8788
'30 minutes': 30 * 60,
@@ -105,7 +106,9 @@ def graph_data_api():
105106
start_time = end_time - time_range_seconds
106107

107108
# Determine the step based on the time range
108-
if time_range_seconds <= 900: # 15 minutes
109+
if time_range_seconds <= 60: # 15 minutes
110+
step = '2s'
111+
elif time_range_seconds <= 900: # 15 minutes
109112
step = '10s'
110113
elif time_range_seconds <= 3600: # 1 hour
111114
step = '30s'

src/routes/helper/unique_id_helper.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
import subprocess
3+
import functools
4+
5+
number_of_sum_check_digits = 5
6+
7+
def calculate_checksum(unique_id, num_of_digits=2):
8+
"""Calculate a simple checksum for the given unique ID."""
9+
checksum = sum((index + 1) * ord(char) for index, char in enumerate(unique_id))
10+
return checksum % (10 ** num_of_digits)
11+
12+
def get_os_installation_uuid():
13+
"""Retrieve the OS installation UUID."""
14+
try:
15+
if os.path.exists('/etc/machine-id'):
16+
with open('/etc/machine-id', 'r') as f:
17+
return f.read().strip()
18+
elif os.path.exists('/var/lib/dbus/machine-id'):
19+
with open('/var/lib/dbus/machine-id', 'r') as f:
20+
return f.read().strip()
21+
else:
22+
return "OS Installation UUID not found."
23+
except Exception as e:
24+
return f"Error reading OS Installation UUID: {str(e)}"
25+
26+
def get_motherboard_serial(sudo_password):
27+
"""Retrieve the motherboard serial number using sudo password."""
28+
try:
29+
command = f"echo {sudo_password} | sudo -S dmidecode -s baseboard-serial-number"
30+
output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT)
31+
return output.decode().strip()
32+
except subprocess.CalledProcessError as e:
33+
return "Error retrieving Motherboard Serial: " + e.output.decode().strip()
34+
except Exception as e:
35+
return f"Unexpected error: {str(e)}"
36+
37+
@functools.lru_cache(maxsize=1)
38+
def calculate_unique_system_id(sudo_password):
39+
"""Calculate a unique system identifier using various hardware IDs."""
40+
os_uuid = get_os_installation_uuid()
41+
motherboard_serial = get_motherboard_serial(sudo_password)
42+
unique_id = f"{os_uuid}:{motherboard_serial}"
43+
unique_id = ''.join(e for e in unique_id if e.isalnum())
44+
checksum = calculate_checksum(unique_id, number_of_sum_check_digits)
45+
unique_id += f"{checksum}"
46+
return unique_id

src/routes/other.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from src.utils import get_os_release_info, get_os_info
1111
from src.helper import check_installation_information
1212
from src.routes.helper.common_helper import admin_required
13+
from src.routes.helper.unique_id_helper import calculate_unique_system_id
1314

1415
other_bp = blueprints.Blueprint('other', __name__)
1516

@@ -111,8 +112,14 @@ def about():
111112
# fetch sg_installation_method from .bashrc file
112113
sg_installation_method = fetch_bashrc_variable("sg_installation_method")
113114
installation_info["sg_installation_method"] = sg_installation_method
115+
sudo_password = session.get('sudo_password', '')
116+
systemguard_unique_id = calculate_unique_system_id(sudo_password)
117+
# store the unique id in session
118+
session['systemguard_unique_id'] = systemguard_unique_id
119+
114120
return render_template("other/about.html",
115-
installation_info=installation_info)
121+
installation_info=installation_info,
122+
systemguard_unique_id=systemguard_unique_id)
116123

117124

118125
@app.route('/os_info', methods=['GET'])

src/templates/graphs/historical_system_metrics.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ <h2><i class="fas fa-clock"></i> Current Server Time & Time Zone</h2>
3434
<div class="time-filter-container">
3535
<label for="timeFilter">Select Time Filter:</label>
3636
<select id="timeFilter">
37+
<option value="1 minute">Last 1 Minute</option>
3738
<option value="5 minutes">Last 5 Minutes</option>
3839
<option value="15 minutes">Last 15 Minutes</option>
3940
<option value="30 minutes">Last 30 Minutes</option>

src/templates/other/about.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ <h5 class="card-title">Author</h5>
2929
<h5 class="card-title">Year</h5>
3030
<p class="card-text mb-0">{{ year }}</p>
3131
</div>
32+
<!-- systemguard_unique_id -->
33+
<div class="info-section">
34+
<h5 class="card-title">SystemGuard Unique ID</h5>
35+
<p class="card-text mb-0">{{ systemguard_unique_id }}</p>
36+
</div>
3237
<div class="info-section">
3338
<h5 class="card-title">Installation Method</h5>
3439
{% if installation_info["sg_installation_method"] == "git" %}

0 commit comments

Comments
 (0)