Added HTTP basic auth, default octoprint config

Added HTTP basic auth to MJPG stream, so now you don't have to worry
about creeps watching your printer

Nginx now runs as www-data

Frontend specific files are no longer put into /etc/skel, they are now
only installed to the kiosk account

OctoPrint now has a default config so that users don't have to configure
system stuff (ex. You don't have to input /webcam/ into the stream box
anymore)

Restart Browser button now kills old Surf sessions

The Raspberry Pi now starts with the Raspberry Pi cameras enabled on
first boot

OctoPrint can now shutdown, reboot and restart its own service using
sudo without a password

Kiosk account no longer has a password since you aren't supposed to
login as kiosk anyways
This commit is contained in:
Logan G 2020-08-26 21:30:10 -06:00
parent 09eac865c0
commit c7f44ec412
Signed by: logan
GPG key ID: E328528C921E7A7A
18 changed files with 110 additions and 25 deletions

View file

@ -4,9 +4,6 @@
- Add network configuration (replace nmtui)
- Add hostname configuration (replace nmtui)
## Nginx
- Add HTTP basic auth (especially to MJPG)
## Misc
- More security
- Wiki

View file

@ -66,3 +66,4 @@ max_framebuffers=2
[all]
#dtoverlay=vc4-fkms-v3d
arm_64bit=1
start_x=1

View file

@ -3,13 +3,8 @@
install -d "${ROOTFS_DIR}/etc/systemd/system/getty@tty1.service.d"
install -m 644 files/noclear.conf "${ROOTFS_DIR}/etc/systemd/system/getty@tty1.service.d/noclear.conf"
install -v -m 644 files/fstab "${ROOTFS_DIR}/etc/fstab"
install -m 755 files/.xprofile "${ROOTFS_DIR}/etc/skel/.xprofile"
install -m 755 files/.browser.sh "${ROOTFS_DIR}/etc/skel/.browser.sh"
install -m 644 files/.dialogrc "${ROOTFS_DIR}/etc/skel/.dialogrc"
install -m 644 files/.dialogrc "${ROOTFS_DIR}/root/.dialogrc"
mkdir -p "${ROOTFS_DIR}/etc/skel/.config/openbox"
install -m 644 files/autostart "${ROOTFS_DIR}/etc/skel/.config/openbox/autostart"
install -m 644 files/menu.xml "${ROOTFS_DIR}/etc/skel/.config/openbox/menu.xml"
on_chroot << EOF
if ! id -u ${FIRST_USER_NAME} >/dev/null 2>&1; then
@ -22,6 +17,5 @@ if ! id -u kiosk >/dev/null 2>&1; then
adduser --disabled-password --shell /usr/sbin/nologin --gecos "" kiosk
fi
echo "${FIRST_USER_NAME}:${FIRST_USER_PASS}" | chpasswd
echo "kiosk:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd
echo "root:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd
EOF

View file

@ -1,13 +1,24 @@
#!/bin/bash -e
install -m 644 files/octoprint.service ${ROOTFS_DIR}/etc/systemd/system/octoprint.service
mkdir -p ${ROOTFS_DIR}/home/octoprint/.octoprint/
install -m 600 files/config.yaml ${ROOTFS_DIR}/home/octoprint/.octoprint/config.yaml
install -m 644 files/nginx.conf ${ROOTFS_DIR}/etc/nginx/nginx.conf
echo -e "listen 443;" > ${ROOTFS_DIR}/etc/nginx/listen.conf
mkdir -p ${ROOTFS_DIR}/usr/local/bin
install -m 755 files/restart-octoprint ${ROOTFS_DIR}/usr/local/bin/restart-octoprint
# Yeah I could've used polkit, but this works fine so whatever
mkdir -p ${ROOTFS_DIR}/etc/sudoers.d
echo "octoprint ALL=NOPASSWD: /sbin/shutdown" > ${ROOTFS_DIR}/etc/sudoers.d/octoprint-shutdown
echo "octoprint ALL=NOPASSWD: /usr/local/bin/restart-octoprint" > ${ROOTFS_DIR}/etc/sudoers.d/octoprint-restart
on_chroot << EOF
# Package enables this when installed, won't start until first-time is run due to missing SSL certs
systemctl disable nginx
# If OctoPrint already exists, skip this (for debugging)
if [[ ! -f /srv/octoprint/bin/octoprint ]]; then
cd /srv/ || exit 1
@ -17,7 +28,6 @@ if [[ ! -f /srv/octoprint/bin/octoprint ]]; then
pip install octoprint || exit 1
# Fix permissions
chown -R octoprint:octoprint /srv/octoprint
chown -R octoprint:octoprint /home/octoprint
fi
# Enable the reverse proxy
systemctl enable nginx
EOF

View file

@ -0,0 +1,10 @@
webcam:
stream: /webcam/
ffmpeg: /usr/bin/ffmpeg
discovery:
publicPort: 443
server:
commands:
systemShutdownCommand: sudo shutdown now
systemRestartCommand: sudo shutdown -r now
serverRestartCommand: sudo restart-octoprint

View file

@ -1,4 +1,5 @@
worker_processes auto;
user www-data;
events {
worker_connections 1024;
@ -46,6 +47,7 @@
}
location /webcam/ {
include /etc/nginx/auth.conf;
proxy_pass http://mjpg-streamer/;
}

View file

@ -6,7 +6,7 @@ Wants=nginx.service
Type=simple
User=octoprint
Group=octoprint
ExecStart=/srv/octoprint/bin/octoprint --host localhost --port 5000
ExecStart=/srv/octoprint/bin/octoprint serve --host localhost --port 5000
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,8 @@
#!/bin/bash
if [ "$EUID" -ne 0 ]; then
echo "This script needs to be run as root."
exit 1
fi
systemctl restart octoprint

View file

@ -1,6 +1,2 @@
cmake
libjpeg-dev
v4l-utils
libv4l-dev
gcc
g++

View file

@ -69,7 +69,6 @@ dialog --title "NOTICE" --nocancel --colors --msgbox "This collection of softwar
# Force the user to change the pi user's password before the RPi gets botnetted
change_password
# Randomize the root and frontend password
echo "kiosk:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd
echo "root:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd
dialog --title "Network Configuration" --nocancel --msgbox "Setup will now open nmtui, a program to help configure your ethernet/wireless interfaces. Hit Quit when you are done." 10 50
@ -92,11 +91,12 @@ openssl req -x509 -nodes -days 36500 -newkey rsa:4096 -subj "/C=/ST=/L=/O=/OU=/C
# If OctoPrint/MJPG Streamer is running locally, ask if the user wants to change the default listening port/IP (optional)
if ( [[ -f /etc/systemd/system/multi-user.target.wants/octoprint.service ]] || [[ -f /etc/systemd/system/multi-user.target.wants/mjpg-streamer.service ]] ) && dialog --title "Nginx Config" --defaultno --yesno "Do you wish to change the default Nginx listening address and/or port?" 10 60; then
nginx_config
nginx_listen
fi
# If MJPG service is enabled, ask user which video device to use
# If MJPG service is enabled, ask the user to configure Nginx basic auth and the video device
if [[ -f /etc/systemd/system/multi-user.target.wants/mjpg-streamer.service ]]; then
nginx_auth
video_select
video_config
fi
@ -111,4 +111,7 @@ fi
# Delete the autologin override and first-time setup utility
rm /etc/systemd/system/getty@tty1.service.d/override.conf
rm /etc/profile.d/first-time.sh
dialog --title "TouchPrint Config" --infobox "Rebooting..." 0 0
sleep 1
reboot

View file

@ -22,7 +22,10 @@ main_menu () {
"2") change_password; main_menu; return 0;;
"3") services_menu; main_menu; return 0;;
"4") screen_timeout; main_menu; return 0;;
"5") dialog --title "Touchscreen Calibration" --infobox "Waiting for touchscreen calibrator to close..." 3 50; DISPLAY=:0 xinput_calibrator --no-timeout --output-filename /etc/X11/xorg.conf.d/99-calibration.conf; main_menu; return 0;;
"5") dialog --title "Touchscreen Calibration" --infobox "Waiting for touchscreen calibrator to close..." 3 50;
DISPLAY=:0 xinput_calibrator --no-timeout --output-filename /etc/X11/xorg.conf.d/99-calibration.conf;
main_menu;
return 0;;
"6") return 0;;
esac
}
@ -38,7 +41,7 @@ services_menu () {
case $SERVICESMENU in
"1") service_toggle; services_menu; return 0;;
"2") service_health; services_menu; return 0;;
"3") nginx_config; services_menu; return 0;;
"3") nginx_menu; services_menu; return 0;;
"4") video_menu; services_menu; return 0;;
"5") return 0;;
esac
@ -67,6 +70,19 @@ service_health () {
\ZnSSH: \Zb$(if pgrep sshd >/dev/null; then echo '\Z2Online'; elif [[ ! -f /etc/systemd/system/multi-user.target.wants/sshd.service ]]; then echo "Disabled"; else echo '\Z1Offline'; fi)" 0 0
}
nginx_menu () {
local NGINXMENU=$(dialog --title "Nginx Config" --menu "" 10 50 0 \
"1" "Listening Settings" \
"2" "MJPG Authentication" \
"3" "Go Back" 3>&1 1>&2 2>&3)
case $NGINXMENU in
"1") nginx_listen; nginx_menu; return 0;;
"2") nginx_auth; nginx_menu; return 0;;
"3") return 0;;
esac
}
video_menu () {
local VIDEOMENU=$(dialog --title "MJPG Config" --menu "" 10 50 0 \
"1" "Camera Selection" \

View file

@ -57,6 +57,12 @@ service_toggle () {
raspi-config nonint do_camera 1 # Disables the camera
fi
if [[ $ENABLE_OCTO == true ]] && [[ $ENABLE_MJPG == true ]]; then
systemctl enable nginx
elif [[ $ENABLE_OCTO == false ]] && [[ $ENABLE_MJPG == false ]]; then
systemctl disable nginx
fi
if [[ $ENABLE_GUI == true ]]; then
systemctl set-default graphical.target
else
@ -101,7 +107,7 @@ screen_timeout () {
EOF
}
nginx_config () {
nginx_listen () {
local LISTEN=""
# Grab the variable from the nginx conf if it exists, otherwise use default
@ -119,6 +125,37 @@ nginx_config () {
echo "listen $LISTEN;" > /etc/nginx/listen.conf
}
nginx_auth () {
local NGINXAUTH_MENU=$(dialog --colors --nocancel --insecure --title "Nginx Config" --mixedform "Input desired username and password for the MJPG stream.\n\nLeave both fields blank if you do not want authentication \Zb\Z1(NOT RECOMMENDED)\Zn." 12 60 0\
"Username: " 1 1 "" 1 11 10 0 0 \
"Password: " 2 1 "" 2 11 30 0 1 3>&1 1>&2 2>&3 || return 0)
NGINXAUTH_MENU=($NGINXAUTH_MENU)
# If all the fields are blank, remove the auth stuff and exit
if [[ "${NGINXAUTH_MENU[*]}" == "" ]]; then
echo "" > /etc/nginx/auth.conf
rm /etc/nginx/.htpasswd
return 0
fi
# If only one of them is blank, make the user start over
if [[ ${NGINXAUTH_MENU[0]} == "" ]] || [[ ${NGINXAUTH_MENU[1]} == "" ]]; then
dialog --title "Error" --msgbox "Invalid input!" 10 50
nginx_auth
return 0
fi
# Write the auth config and password file to Nginx
echo -e "satisfy any;\nallow 127.0.0.1;\ndeny all;\nauth_basic \"TouchPrint MJPG Stream\";\nauth_basic_user_file /etc/nginx/.htpasswd;" > /etc/nginx/auth.conf
#htpasswd -b -B -c /etc/nginx/.htpasswd ${NGINXAUTH_MENU[0]} ${NGINXAUTH_MENU[1]}
echo "${NGINXAUTH_MENU[0]}:$(openssl passwd -apr1 ${NGINXAUTH_MENU[1]})" > /etc/nginx/.htpasswd
unset NGINXAUTH_MENU
# Set perms so that no one steals our precious password hashes
chown root:www-data /etc/nginx/.htpasswd
chmod 640 /etc/nginx/.htpasswd
}
video_select () {
# In the unlikely event that there are no video devices, don't continue
if ! ls /dev/video* 2>&1 >/dev/null; then
@ -165,7 +202,7 @@ video_config () {
"Framerate: " 2 1 "$FRAMERATE" 2 12 3 0 3>&1 1>&2 2>&3)
VIDEOCONFIG_MENU=($VIDEOCONFIG_MENU)
if [[ "$VIDEOCONFIG_MENU[0]" == "" ]] || [[ "$VIDEOCONFIG_MENU[1]" == "" ]]; then
if [[ "${VIDEOCONFIG_MENU[0]}" == "" ]] || [[ "${VIDEOCONFIG_MENU[1]}" == "" ]]; then
dialog --title "Error" --msgbox "Invalid input!" 10 50
video_config
return 0

10
stage3/02-kiosk/00-run.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash -e
mkdir -p "${ROOTFS_DIR}/home/kiosk"
install -m 755 files/.xprofile "${ROOTFS_DIR}/home/kiosk/.xprofile"
install -m 755 files/.browser.sh "${ROOTFS_DIR}/home/kiosk/.browser.sh"
mkdir -p "${ROOTFS_DIR}/home/kiosk/.config/openbox"
install -m 644 files/autostart "${ROOTFS_DIR}/home/kiosk/.config/openbox/autostart"
install -m 644 files/menu.xml "${ROOTFS_DIR}/home/kiosk/.config/openbox/menu.xml"

View file

@ -7,6 +7,7 @@
<menu id="root-menu" label="Openbox 3">
<item label="Restart Browser">
<action name="Execute"><execute>killall surf</execute></action>
<action name="Execute"><execute>bash ~/.browser.sh</execute></action>
</item>
<separator />