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 network configuration (replace nmtui)
- Add hostname configuration (replace nmtui) - Add hostname configuration (replace nmtui)
## Nginx
- Add HTTP basic auth (especially to MJPG)
## Misc ## Misc
- More security - More security
- Wiki - Wiki

View file

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

View file

@ -3,13 +3,8 @@
install -d "${ROOTFS_DIR}/etc/systemd/system/getty@tty1.service.d" 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 -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 -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}/etc/skel/.dialogrc"
install -m 644 files/.dialogrc "${ROOTFS_DIR}/root/.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 on_chroot << EOF
if ! id -u ${FIRST_USER_NAME} >/dev/null 2>&1; then 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 adduser --disabled-password --shell /usr/sbin/nologin --gecos "" kiosk
fi fi
echo "${FIRST_USER_NAME}:${FIRST_USER_PASS}" | chpasswd 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 echo "root:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd
EOF EOF

View file

@ -1,13 +1,24 @@
#!/bin/bash -e #!/bin/bash -e
install -m 644 files/octoprint.service ${ROOTFS_DIR}/etc/systemd/system/octoprint.service 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 install -m 644 files/nginx.conf ${ROOTFS_DIR}/etc/nginx/nginx.conf
echo -e "listen 443;" > ${ROOTFS_DIR}/etc/nginx/listen.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 on_chroot << EOF
# Package enables this when installed, won't start until first-time is run due to missing SSL certs # Package enables this when installed, won't start until first-time is run due to missing SSL certs
systemctl disable nginx systemctl disable nginx
# If OctoPrint already exists, skip this (for debugging) # If OctoPrint already exists, skip this (for debugging)
if [[ ! -f /srv/octoprint/bin/octoprint ]]; then if [[ ! -f /srv/octoprint/bin/octoprint ]]; then
cd /srv/ || exit 1 cd /srv/ || exit 1
@ -17,7 +28,6 @@ if [[ ! -f /srv/octoprint/bin/octoprint ]]; then
pip install octoprint || exit 1 pip install octoprint || exit 1
# Fix permissions # Fix permissions
chown -R octoprint:octoprint /srv/octoprint chown -R octoprint:octoprint /srv/octoprint
chown -R octoprint:octoprint /home/octoprint
fi fi
# Enable the reverse proxy
systemctl enable nginx
EOF 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; worker_processes auto;
user www-data;
events { events {
worker_connections 1024; worker_connections 1024;
@ -46,6 +47,7 @@
} }
location /webcam/ { location /webcam/ {
include /etc/nginx/auth.conf;
proxy_pass http://mjpg-streamer/; proxy_pass http://mjpg-streamer/;
} }

View file

@ -6,7 +6,7 @@ Wants=nginx.service
Type=simple Type=simple
User=octoprint User=octoprint
Group=octoprint Group=octoprint
ExecStart=/srv/octoprint/bin/octoprint --host localhost --port 5000 ExecStart=/srv/octoprint/bin/octoprint serve --host localhost --port 5000
[Install] [Install]
WantedBy=multi-user.target 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 libjpeg-dev
v4l-utils
libv4l-dev 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 # Force the user to change the pi user's password before the RPi gets botnetted
change_password change_password
# Randomize the root and frontend 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 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 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 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 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 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 if [[ -f /etc/systemd/system/multi-user.target.wants/mjpg-streamer.service ]]; then
nginx_auth
video_select video_select
video_config video_config
fi fi
@ -111,4 +111,7 @@ fi
# Delete the autologin override and first-time setup utility # Delete the autologin override and first-time setup utility
rm /etc/systemd/system/getty@tty1.service.d/override.conf rm /etc/systemd/system/getty@tty1.service.d/override.conf
rm /etc/profile.d/first-time.sh rm /etc/profile.d/first-time.sh
dialog --title "TouchPrint Config" --infobox "Rebooting..." 0 0
sleep 1
reboot reboot

View file

@ -22,7 +22,10 @@ main_menu () {
"2") change_password; main_menu; return 0;; "2") change_password; main_menu; return 0;;
"3") services_menu; main_menu; return 0;; "3") services_menu; main_menu; return 0;;
"4") screen_timeout; 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;; "6") return 0;;
esac esac
} }
@ -38,7 +41,7 @@ services_menu () {
case $SERVICESMENU in case $SERVICESMENU in
"1") service_toggle; services_menu; return 0;; "1") service_toggle; services_menu; return 0;;
"2") service_health; 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;; "4") video_menu; services_menu; return 0;;
"5") return 0;; "5") return 0;;
esac 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 \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 () { video_menu () {
local VIDEOMENU=$(dialog --title "MJPG Config" --menu "" 10 50 0 \ local VIDEOMENU=$(dialog --title "MJPG Config" --menu "" 10 50 0 \
"1" "Camera Selection" \ "1" "Camera Selection" \

View file

@ -57,6 +57,12 @@ service_toggle () {
raspi-config nonint do_camera 1 # Disables the camera raspi-config nonint do_camera 1 # Disables the camera
fi 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 if [[ $ENABLE_GUI == true ]]; then
systemctl set-default graphical.target systemctl set-default graphical.target
else else
@ -101,7 +107,7 @@ screen_timeout () {
EOF EOF
} }
nginx_config () { nginx_listen () {
local LISTEN="" local LISTEN=""
# Grab the variable from the nginx conf if it exists, otherwise use default # 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 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 () { video_select () {
# In the unlikely event that there are no video devices, don't continue # In the unlikely event that there are no video devices, don't continue
if ! ls /dev/video* 2>&1 >/dev/null; then 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) "Framerate: " 2 1 "$FRAMERATE" 2 12 3 0 3>&1 1>&2 2>&3)
VIDEOCONFIG_MENU=($VIDEOCONFIG_MENU) 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 dialog --title "Error" --msgbox "Invalid input!" 10 50
video_config video_config
return 0 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"> <menu id="root-menu" label="Openbox 3">
<item label="Restart Browser"> <item label="Restart Browser">
<action name="Execute"><execute>killall surf</execute></action>
<action name="Execute"><execute>bash ~/.browser.sh</execute></action> <action name="Execute"><execute>bash ~/.browser.sh</execute></action>
</item> </item>
<separator /> <separator />