2018-04-05 21:12:36 +02:00
|
|
|
#!/usr/bin/env python3
|
2018-02-13 23:59:23 +01:00
|
|
|
# Installation script to install howdy
|
2018-04-05 21:12:36 +02:00
|
|
|
# Executed after primary apt install
|
2018-02-13 23:59:23 +01:00
|
|
|
|
|
|
|
# Import required modules
|
2018-02-05 23:43:32 +01:00
|
|
|
import subprocess
|
|
|
|
import time
|
|
|
|
import sys
|
|
|
|
import os
|
2018-02-13 15:00:30 +01:00
|
|
|
import re
|
2018-02-05 23:43:32 +01:00
|
|
|
import signal
|
|
|
|
import fileinput
|
|
|
|
import urllib.parse
|
|
|
|
|
2018-04-12 19:38:34 +02:00
|
|
|
if "configure" not in sys.argv:
|
|
|
|
sys.exit(0)
|
|
|
|
|
2018-02-05 23:43:32 +01:00
|
|
|
def log(text):
|
2018-02-13 23:59:23 +01:00
|
|
|
"""Print a nicely formatted line to stdout"""
|
2018-02-08 01:11:47 +01:00
|
|
|
print("\n>>> \033[32m" + text + "\033[0m\n")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
|
|
|
def handleStatus(status):
|
2018-02-13 23:59:23 +01:00
|
|
|
"""Abort if a command fails"""
|
2018-02-08 01:11:47 +01:00
|
|
|
if (status != 0):
|
|
|
|
print("\033[31mError while running last command\033[0m")
|
2018-04-05 21:12:36 +02:00
|
|
|
sys.exit(1)
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-04-05 21:46:11 +02:00
|
|
|
|
2018-04-12 19:38:34 +02:00
|
|
|
# We're not in fresh configuration mode, so exit
|
|
|
|
if not os.path.exists("/tmp/howdy_picked_device"):
|
|
|
|
sys.exit(0)
|
2018-04-05 21:12:36 +02:00
|
|
|
|
2018-04-12 19:38:34 +02:00
|
|
|
in_file = open("/tmp/howdy_picked_device", "r")
|
2018-04-12 23:45:52 +02:00
|
|
|
# Should be a string
|
|
|
|
picked = in_file.read()
|
2018-04-12 19:38:34 +02:00
|
|
|
in_file.close()
|
2018-04-05 21:12:36 +02:00
|
|
|
|
2018-04-12 19:38:34 +02:00
|
|
|
subprocess.call(["rm /tmp/howdy_picked_device"], shell=True)
|
2018-04-05 21:12:36 +02:00
|
|
|
|
2018-04-12 23:45:52 +02:00
|
|
|
log("Upgrading pip to the latest version")
|
|
|
|
|
2018-04-12 19:38:34 +02:00
|
|
|
# Update pip
|
|
|
|
handleStatus(subprocess.call(["pip3 install --upgrade pip"], shell=True))
|
2018-02-05 23:43:32 +01:00
|
|
|
|
|
|
|
log("Cloning dlib")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Clone the git to /tmp
|
2018-04-12 23:45:52 +02:00
|
|
|
handleStatus(subprocess.call(["git", "clone", "--depth", "1", "https://github.com/davisking/dlib.git", "/tmp/dlib_clone"]))
|
2018-02-05 23:43:32 +01:00
|
|
|
|
|
|
|
log("Building dlib")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Start the build without GPU
|
2018-02-05 23:43:32 +01:00
|
|
|
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")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Remove the no longer needed git clone
|
2018-02-05 23:43:32 +01:00
|
|
|
handleStatus(subprocess.call(["rm", "-rf", "/tmp/dlib_clone"]))
|
2018-04-07 19:15:00 +02:00
|
|
|
print("Temporary dlib files removed")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-04-12 23:45:52 +02:00
|
|
|
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"]))
|
|
|
|
|
2018-02-05 23:43:32 +01:00
|
|
|
log("Installing face_recognition")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Install face_recognition though pip
|
2018-04-12 23:45:52 +02:00
|
|
|
handleStatus(subprocess.call(["pip3", "install", "--cache-dir", "/tmp/pip_howdy", "--no-deps", "face_recognition==1.2.2"]))
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-04-07 19:15:00 +02:00
|
|
|
log("Configuring howdy")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Manually change the camera id to the one picked
|
2018-02-05 23:43:32 +01:00
|
|
|
for line in fileinput.input(["/lib/security/howdy/config.ini"], inplace = 1):
|
2018-02-08 01:11:47 +01:00
|
|
|
print(line.replace("device_id = 1", "device_id = " + picked), end="")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-10 17:03:42 +01:00
|
|
|
# Secure the howdy folder
|
2018-02-05 23:43:32 +01:00
|
|
|
handleStatus(subprocess.call(["chmod 600 -R /lib/security/howdy/"], shell=True))
|
2018-02-10 17:03:42 +01:00
|
|
|
|
2018-04-07 17:39:14 +02:00
|
|
|
# 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))
|
2018-04-07 19:15:00 +02:00
|
|
|
print("Permissions set")
|
2018-04-07 17:39:14 +02:00
|
|
|
|
|
|
|
# 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))
|
2018-04-07 19:15:00 +02:00
|
|
|
print("Installing howdy command")
|
2018-04-07 17:39:14 +02:00
|
|
|
|
2018-02-13 15:00:30 +01:00
|
|
|
# Install the command autocomplete, don't error on failure
|
2018-04-07 16:22:13 +02:00
|
|
|
# subprocess.call(["sudo cp /lib/security/howdy/autocomplete.sh /etc/bash_completion.d/howdy"], shell=True)
|
2018-02-10 17:03:42 +01:00
|
|
|
|
2018-02-05 23:43:32 +01:00
|
|
|
log("Adding howdy as PAM module")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Will be filled with the actual output lines
|
2018-02-05 23:43:32 +01:00
|
|
|
outlines = []
|
2018-02-13 23:59:23 +01:00
|
|
|
# Will be fillled with lines that contain coloring
|
2018-02-05 23:43:32 +01:00
|
|
|
printlines = []
|
2018-02-13 23:59:23 +01:00
|
|
|
# Track if the new lines have been insterted yet
|
2018-02-05 23:43:32 +01:00
|
|
|
inserted = False
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Open the PAM config file
|
2018-02-05 23:43:32 +01:00
|
|
|
with open("/etc/pam.d/common-auth") as fp:
|
2018-02-13 23:59:23 +01:00
|
|
|
# Read the first line
|
2018-02-08 01:11:47 +01:00
|
|
|
line = fp.readline()
|
2018-02-13 23:59:23 +01:00
|
|
|
|
2018-02-08 01:11:47 +01:00
|
|
|
while line:
|
2018-02-13 23:59:23 +01:00
|
|
|
# Add the line to the output directly, we're not deleting anything
|
2018-02-08 01:11:47 +01:00
|
|
|
outlines.append(line)
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Print the comments in gray and don't insert into comments
|
|
|
|
if line[:1] == "#":
|
|
|
|
printlines.append("\033[37m" + line + "\033[0m")
|
|
|
|
else:
|
2018-02-08 01:11:47 +01:00
|
|
|
printlines.append(line)
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# If it's not a comment and we haven't inserted yet
|
2018-02-08 01:11:47 +01:00
|
|
|
if not inserted:
|
2018-02-13 23:59:23 +01:00
|
|
|
# Set both the comment and the linking line
|
2018-02-08 01:11:47 +01:00
|
|
|
line_comment = "# Howdy IR face recognition\n"
|
2018-02-13 23:59:23 +01:00
|
|
|
line_link = "auth sufficient pam_python.so /lib/security/howdy/pam.py\n\n"
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Add them to the output without any markup
|
2018-02-08 01:11:47 +01:00
|
|
|
outlines.append(line_comment)
|
2018-02-13 23:59:23 +01:00
|
|
|
outlines.append(line_link)
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Make the print orange to make it clear what's being added
|
2018-02-08 01:11:47 +01:00
|
|
|
printlines.append("\033[33m" + line_comment + "\033[0m")
|
2018-02-13 23:59:23 +01:00
|
|
|
printlines.append("\033[33m" + line_link + "\033[0m")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Mark as inserted
|
2018-02-08 01:11:47 +01:00
|
|
|
inserted = True
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Go to the next line
|
2018-02-08 01:11:47 +01:00
|
|
|
line = fp.readline()
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Print a file Header
|
2018-02-05 23:43:32 +01:00
|
|
|
print("\033[33m" + ">>> START OF /etc/pam.d/common-auth" + "\033[0m")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Loop though all printing lines and use the enters from the file
|
2018-02-05 23:43:32 +01:00
|
|
|
for line in printlines:
|
2018-02-08 01:11:47 +01:00
|
|
|
print(line, end="")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Print a footer
|
2018-02-05 23:43:32 +01:00
|
|
|
print("\033[33m" + ">>> END OF /etc/pam.d/common-auth" + "\033[0m" + "\n")
|
|
|
|
|
2018-04-05 21:12:36 +02:00
|
|
|
# Do not prompt for a yes if we're in no promt mode
|
2018-04-05 21:46:11 +02:00
|
|
|
if "HOWDY_NO_PROMPT" not in os.environ:
|
2018-04-05 21:12:36 +02:00
|
|
|
# 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]: ")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-04-05 21:12:36 +02:00
|
|
|
# Abort the whole thing if it's not
|
|
|
|
if (ans.lower() != "y"):
|
|
|
|
print("Inerpeting as a \"NO\", aborting")
|
|
|
|
sys.exit(1)
|
2018-02-05 23:43:32 +01:00
|
|
|
|
|
|
|
print("Adding lines to PAM\n")
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Write to PAM
|
2018-02-05 23:43:32 +01:00
|
|
|
common_auth = open("/etc/pam.d/common-auth", "w")
|
|
|
|
common_auth.write("".join(outlines))
|
|
|
|
common_auth.close()
|
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# From here onwards the installation is complete
|
|
|
|
# We want to gather more information about the types or IR camera's
|
2018-04-07 17:22:30 +02:00
|
|
|
# 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")
|
2018-02-05 23:43:32 +01:00
|
|
|
|
2018-02-13 23:59:23 +01:00
|
|
|
# Let the user know what to do with the link
|
2018-02-05 23:43:32 +01:00
|
|
|
print("Installation complete.")
|
2018-04-07 17:09:42 +02:00
|
|
|
print("\033[33mIf you want to help the development, please use the link above to post some camera-related information to github!\033[0m")
|