0
0
Fork 0
mirror of https://github.com/boltgolt/howdy.git synced 2024-09-19 09:51:19 +02:00
howdy/debian/postinst
boltgolt 22cc108e87 Added auto config backup and restore for upgarades
This does remove all comments from the config file
2018-05-10 15:05:27 +02:00

230 lines
7.5 KiB
Python
Executable file

#!/usr/bin/env python3
# Installation script to install howdy
# Executed after primary apt install
def col(id):
"""Add color escape sequences"""
if id == 1: return "\033[32m"
if id == 2: return "\033[33m"
if id == 3: return "\033[31m"
return "\033[0m"
# Import required modules
import subprocess
import time
import sys
import os
import re
import signal
import fileinput
import urllib.parse
# Don't run unless we need to configure the install
# Will also happen on upgrade but we will catch that later on
if "configure" not in sys.argv:
sys.exit(0)
def log(text):
"""Print a nicely formatted line to stdout"""
print("\n>>> " + col(1) + text + col(0) + "\n")
def handleStatus(status):
"""Abort if a command fails"""
if (status != 0):
print(col(3) + "Error while running last command" + col(0))
sys.exit(1)
# We're not in fresh configuration mode so don't continue the setup
if not os.path.exists("/tmp/howdy_picked_device"):
# Check if we have an older config we can restore
if len(sys.argv) > 2:
if os.path.exists("/tmp/howdy_config_backup_v" + sys.argv[2] + ".ini"):
# Get the config parser
import configparser
# Load th old and new config files
oldConf = configparser.ConfigParser()
oldConf.read("/tmp/howdy_config_backup_v" + sys.argv[2] + ".ini")
newConf = configparser.ConfigParser()
newConf.read("/lib/security/howdy/config.ini")
# Go through every setting in the old config and apply it to the new file
for section in oldConf.sections():
for (key, value) in oldConf.items(section):
try:
newConf.set(section, key, value)
# Add a new section where needed
except configparser.NoSectionError as e:
newConf.add_section(section)
newConf.set(section, key, value)
# Write it all to file
with open("/lib/security/howdy/config.ini", "w") as configfile:
newConf.write(configfile)
sys.exit(0)
# Open the temporary file containing the device ID
in_file = open("/tmp/howdy_picked_device", "r")
# Load it in, it should be a string
picked = in_file.read()
in_file.close()
# Remove the temporary file
subprocess.call(["rm /tmp/howdy_picked_device"], shell=True)
log("Upgrading pip to the latest version")
# Update pip
handleStatus(subprocess.call(["pip3 install --upgrade pip"], shell=True))
log("Cloning dlib")
# Clone the dlib git to /tmp, but only the last commit
handleStatus(subprocess.call(["git", "clone", "--depth", "1", "https://github.com/davisking/dlib.git", "/tmp/dlib_clone"]))
log("Building dlib")
# Start the build without GPU
handleStatus(subprocess.call(["cd /tmp/dlib_clone/; python3 setup.py install --yes USE_AVX_INSTRUCTIONS --no DLIB_USE_CUDA"], shell=True))
log("Cleaning up dlib")
# Remove the no longer needed git clone
handleStatus(subprocess.call(["rm", "-rf", "/tmp/dlib_clone"]))
print("Temporary dlib files removed")
log("Installing python dependencies")
# Install face_recognition though pip
handleStatus(subprocess.call(["pip3", "install", "--cache-dir", "/tmp/pip_howdy", "face_recognition_models==0.3.0", "Click>=6.0", "numpy", "Pillow"]))
log("Installing face_recognition")
# Install face_recognition though pip
handleStatus(subprocess.call(["pip3", "install", "--cache-dir", "/tmp/pip_howdy", "--no-deps", "face_recognition==1.2.2"]))
log("Configuring howdy")
# Manually change the camera id to the one picked
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace = 1):
print(line.replace("device_id = 1", "device_id = " + picked), end="")
# Secure the howdy folder
handleStatus(subprocess.call(["chmod 600 -R /lib/security/howdy/"], shell=True))
# Allow anyone to execute the python CLI
handleStatus(subprocess.call(["chmod 755 /lib/security/howdy"], shell=True))
handleStatus(subprocess.call(["chmod 744 /lib/security/howdy/cli.py"], shell=True))
handleStatus(subprocess.call(["chmod 744 -R /lib/security/howdy/cli"], shell=True))
print("Permissions set")
# Make the CLI executable as howdy
handleStatus(subprocess.call(["ln -s /lib/security/howdy/cli.py /usr/local/bin/howdy"], shell=True))
handleStatus(subprocess.call(["chmod +x /usr/local/bin/howdy"], shell=True))
print("Howdy command installed")
log("Adding howdy as PAM module")
# Will be filled with the actual output lines
outlines = []
# Will be fillled with lines that contain coloring
printlines = []
# Track if the new lines have been insterted yet
inserted = False
# Open the PAM config file
with open("/etc/pam.d/common-auth") as fp:
# Read the first line
line = fp.readline()
while line:
# Add the line to the output directly, we're not deleting anything
outlines.append(line)
# Print the comments in gray and don't insert into comments
if line[:1] == "#":
printlines.append("\033[37m" + line + "\033[0m")
else:
printlines.append(line)
# If it's not a comment and we haven't inserted yet
if not inserted:
# Set both the comment and the linking line
line_comment = "# Howdy IR face recognition\n"
line_link = "auth sufficient pam_python.so /lib/security/howdy/pam.py\n\n"
# Add them to the output without any markup
outlines.append(line_comment)
outlines.append(line_link)
# Make the print orange to make it clear what's being added
printlines.append("\033[33m" + line_comment + "\033[0m")
printlines.append("\033[33m" + line_link + "\033[0m")
# Mark as inserted
inserted = True
# Go to the next line
line = fp.readline()
# Print a file Header
print("\033[33m" + ">>> START OF /etc/pam.d/common-auth" + "\033[0m")
# Loop though all printing lines and use the enters from the file
for line in printlines:
print(line, end="")
# Print a footer
print("\033[33m" + ">>> END OF /etc/pam.d/common-auth" + "\033[0m" + "\n")
# Do not prompt for a yes if we're in no promt mode
if "HOWDY_NO_PROMPT" not in os.environ:
# Ask the user if this change is okay
print("Lines will be insterted in /etc/pam.d/common-auth as shown above")
ans = input("Apply this change? [y/N]: ")
# Abort the whole thing if it's not
if (ans.lower() != "y"):
print("Interpreting as a \"NO\", aborting")
sys.exit(1)
print("Adding lines to PAM\n")
# Write to PAM
common_auth = open("/etc/pam.d/common-auth", "w")
common_auth.write("".join(outlines))
common_auth.close()
# From here onwards the installation is complete
# We want to gather more information about the types or IR camera's
# used though, and the following lines are data gathering
# No data is ever uploaded without permission
if "HOWDY_NO_PROMPT" not in os.environ:
# List all video devices
diag_out = "Video devices [IR=" + picked + "]\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['ls /dev/ | grep video'], shell=True).decode("utf-8")
diag_out += "```\n"
# Get some info from the USB kernel listings
diag_out += "Lsusb output\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['lsusb -vvvv | grep -i "Camera\|iFunction"'], shell=True).decode("utf-8")
diag_out += "```\n"
# Get camera information from video4linux
diag_out += "Udevadm\n"
diag_out += "```\n"
diag_out += subprocess.check_output(['udevadm info -r --query=all -n /dev/video' + picked + ' | grep -i "ID_BUS\|ID_MODEL_ID\|ID_VENDOR_ID\|ID_V4L_PRODUCT\|ID_MODEL"'], shell=True).decode("utf-8")
diag_out += "```"
# Print it all as a clickable link to a new github issue
print("https://github.com/Boltgolt/howdy-reports/issues/new?title=Post-installation%20camera%20information&body=" + urllib.parse.quote_plus(diag_out) + "\n")
# Let the user know what to do with the link
print("Installation complete.")
print(col(2) + "If you want to help the development, please use the link above to post some camera-related information to github!" + col(0))