Remove special elevated privileges for the Web Interface (#536)

* Use the pi_shutdown method to restart the rascsi service

* Use the pi_shutdown method to restart the rascsi service

* Remove modifications to sudoers no longer needed

* Introduce sleeps attempting to connect to socket; reduce overall number of retries

* Remove systemd helped methods and the functionality that depends on it

* Attempts to speed up splash code

* Remove unneccessary verbosity

* Attempt to optimize service definition
This commit is contained in:
Daniel Markstedt 2021-12-19 15:50:03 -08:00 committed by GitHub
parent 801aebfb96
commit c887edfc8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 20 additions and 89 deletions

View File

@ -113,18 +113,6 @@ function installRaScsiWebInterface() {
sudo usermod -a -G $USER www-data
if [[ `sudo grep -c "rascsi" /etc/sudoers` -eq 0 ]]; then
sudo bash -c 'echo "
# Allow the web server to restart the rascsi service
www-data ALL=NOPASSWD: /bin/systemctl restart rascsi.service
www-data ALL=NOPASSWD: /bin/systemctl stop rascsi.service
# Allow the web server to reboot the raspberry pi
www-data ALL=NOPASSWD: /sbin/shutdown, /sbin/reboot
" >> /etc/sudoers'
else
echo "The sudoers file is already modified for rascsi-web."
fi
sudo systemctl reload nginx || true
}

View File

@ -5,9 +5,10 @@ After=network.target rascsi.service
[Service]
Type=simple
Restart=always
RestartSec=2s
ExecStart=/home/pi/RASCSI/src/oled_monitor/start.sh
ExecStop=/bin/echo "Shutting down the OLED Monitor gracefully..."
ExecStop=/bin/pkill --signal 2 -f "python3 rascsi_oled_monitor.py"
# Sleep 2s as a crude way for the python interrupt handler to take effect and show the shutdown splash
ExecStop=/bin/sleep 2
SyslogIdentifier=RASCSIMON

View File

@ -119,6 +119,11 @@ LINE_SPACING = 8
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
FONT = ImageFont.truetype('type_writer.ttf', FONT_SIZE)
# Load a bitmap image for start and stop splash screens and convert to monocrome
# Make sure the splash bitmap image is in the same dir as this script
SPLASH_START = Image.open(f"splash_start_{HEIGHT}.bmp").convert("1")
SPLASH_STOP = Image.open(f"splash_stop_{HEIGHT}.bmp").convert("1")
IP_ADDR, HOSTNAME = get_ip_and_host()
@ -163,23 +168,18 @@ def formatted_output():
def start_splash():
"""
Displays a splash screen for the startup sequence
Make sure the splash bitmap image is in the same dir as this script
"""
splash = Image.open(f"splash_start_{HEIGHT}.bmp").convert("1")
DRAW.bitmap((0, 0), splash)
OLED.image(splash)
DRAW.bitmap((0, 0), SPLASH_START, fill=0)
OLED.image(SPLASH_START)
OLED.show()
sleep(6)
sleep(4)
def stop_splash():
"""
Displays a splash screen for the shutdown sequence
Make sure the splash bitmap image is in the same dir as this script
"""
DRAW.rectangle((0, 0, WIDTH, HEIGHT), outline=0, fill=0)
splash = Image.open(f"splash_stop_{HEIGHT}.bmp").convert("1")
DRAW.bitmap((0, 0), splash)
OLED.image(splash)
DRAW.bitmap((0, 0), SPLASH_STOP, fill=0)
OLED.image(SPLASH_STOP)
OLED.show()
# Show a startup splash bitmap image before starting the main loop

View File

@ -5,6 +5,7 @@ and receiving results from the RaSCSI backend
import socket
from struct import pack, unpack
from time import sleep
def send_pb_command(payload):
"""
@ -16,7 +17,7 @@ def send_pb_command(payload):
port = 6868
counter = 0
tries = 100
tries = 20
error_msg = ""
while counter < tries:
@ -29,6 +30,7 @@ def send_pb_command(payload):
print("The RaSCSI service is not responding - attempt %s/%s",
str(counter), str(tries))
error_msg = str(error)
sleep(0.2)
exit(error_msg)

View File

@ -60,9 +60,7 @@ fi
# Compiler flags needed for gcc v10 and up
if [[ `gcc --version | awk '/gcc/' | awk -F ' ' '{print $3}' | awk -F '.' '{print $1}'` -ge 10 ]]; then
echo -n "gcc 10 or later detected. Will compile with the following flags: "
COMPILER_FLAGS="-fcommon"
echo $COMPILER_FLAGS
fi
# Test for two known broken venv states

View File

@ -8,20 +8,6 @@ import logging
from settings import AUTH_GROUP
def systemd_service(service, action):
"""
Takes (str) service and (str) action
Action can be any that systemctl supports, ex. start/stop/restart/show
Returns (dict) with (bool) status, (str) msg, (str) err
"""
proc = asyncio.run(run_async(f"sudo /bin/systemctl {action} {service}"))
return {
"status": proc["returncode"] == 0,
"msg": proc["stdout"],
"err": proc["stderr"],
}
def running_env():
"""
Returns (str) git and (str) env

View File

@ -3,7 +3,6 @@ Module for commands sent to the RaSCSI backend service.
"""
from settings import REMOVABLE_DEVICE_TYPES
from pi_cmds import systemd_service
from socket_cmds import send_pb_command
import rascsi_interface_pb2 as proto
@ -363,13 +362,6 @@ def shutdown_pi(mode):
Takes (str) mode as an argument.
Returns (bool) status and (str) msg.
"""
# This section proactively stops the monitor_rascsi systemd service, if running
# Otherwise, the monitor_rascsi script's interrupt handler won't take effect
monitor_service = "monitor_rascsi.service"
monitor_status = systemd_service(monitor_service, "show")
if "ActiveState=active" in monitor_status["msg"]:
systemd_service(monitor_service, "stop")
command = proto.PbCommand()
command.operation = proto.PbOperation.SHUT_DOWN
command.params["mode"] = str(mode)

View File

@ -4,6 +4,7 @@ Module for sending and receiving data over a socket connection with the RaSCSI b
import logging
from flask import abort
from time import sleep
def send_pb_command(payload):
"""
@ -15,7 +16,7 @@ def send_pb_command(payload):
port = 6868
counter = 0
tries = 100
tries = 20
error_msg = ""
import socket
@ -29,6 +30,7 @@ def send_pb_command(payload):
logging.warning("The RaSCSI service is not responding - attempt %s/%s",
str(counter), str(tries))
error_msg = str(error)
sleep(0.2)
logging.error(error_msg)

View File

@ -619,8 +619,8 @@
Raspberry Pi Operations
</summary>
<ul>
<li>Issue reboot or shutdown commands to the Raspberry Pi.</li>
<li>You can also restart the RaSCSI backend service here.</li>
<li>Reboot or shut down the Raspberry Pi that RaSCSI is running on.</li>
<li>IMPORTANT: Always shut down the Pi before turning off the power. Failing to do so may lead to data corruption.</li>
</ul>
</details>
<table style="border: none">
@ -635,11 +635,6 @@
<input type="submit" value="Shut Down Raspberry Pi">
</form>
</td>
<td style="border: none; vertical-align:top;">
<form action="/rascsi/restart" method="post" onsubmit="return confirm('Restart RaSCSI?')">
<input type="submit" value="Restart RaSCSI Service">
</form>
</td>
</tr>
</table>

View File

@ -38,7 +38,6 @@ from file_cmds import (
)
from pi_cmds import (
running_env,
systemd_service,
running_proc,
is_bridge_setup,
disk_space,
@ -661,38 +660,6 @@ def unreserve_id():
flash(process["msg"], "error")
return redirect(url_for("index"))
@APP.route("/rascsi/restart", methods=["POST"])
@login_required
def rascsi_restart():
"""
Restarts the RaSCSI backend service
"""
service = "rascsi.service"
monitor_service = "monitor_rascsi.service"
rascsi_status = systemd_service(service, "show")
if rascsi_status["status"] and "ActiveState=active" not in rascsi_status["msg"]:
flash(
f"Failed to restart {service} because it is inactive. "
"You are probably running RaSCSI as a regular process.", "error"
)
return redirect(url_for("index"))
monitor_status = systemd_service(monitor_service, "show")
restart_proc = systemd_service(service, "restart")
if restart_proc["status"]:
flash(f"Restarted {service}")
restart_monitor = systemd_service(monitor_service, "restart")
if restart_monitor["status"] and "ActiveState=active" in monitor_status["msg"]:
flash(f"Restarted {monitor_service}")
elif not restart_monitor["status"] and "ActiveState=active" in monitor_status["msg"]:
flash(f"Failed to restart {monitor_service}:", "error")
return redirect(url_for("index"))
restart_monitor = systemd_service("monitor_rascsi.service", "restart")
flash(f"Failed to restart {service}:", "error")
flash(restart_proc["err"], "error")
return redirect(url_for("index"))
@APP.route("/pi/reboot", methods=["POST"])
@login_required