#!/usr/bin/env python3
#-*- coding:utf-8 -*-
"Sensible labtest with automatic recommendation (final say is always human)."
__copyright__ = "Copyright 2017 Tero Karvinen http://TeroKarvinen.com"

import logging
from logging import error, warning, info, debug
import argparse
from subprocess import run, PIPE, DEVNULL
import re

def parseArgs():
        parser = argparse.ArgumentParser(fromfile_prefix_chars="@",
                description=__doc__, epilog=__copyright__)
        parser.add_argument("-v", "--verbose", 
                action="store_const", dest="log_level",
                const=logging.INFO, default=logging.WARNING)
        parser.add_argument("-d", "--debug",
                action="store_const", dest="log_level",
                const=logging.DEBUG)
        return parser.parse_args()

def runOK(cmd):
	"Return True if command returned succesful exit status"
	ret = run(cmd, stdout=PIPE, stderr=PIPE, shell=True)
	OK = ret.returncode==0
	if OK: 
		info("OK: %s" % cmd)
	else:
		info("FAIL: %s" % cmd)
	debug("	%s\n%s\n" % (ret.stdout, ret.stderr));
	return OK

def mustFail(cmds):
	return mustOK(cmds, mustFail=True)

def mustOK(cmds, mustFail=False):
	cmds=cmds.strip()
	cmdList=cmds.split("\n")
	max=len(cmdList)
	pts=0
	for cmd in cmdList:
		cmd=cmd.strip()
		ok = runOK(cmd)
		if ok and not mustFail:
			pts+=1
		if not ok and mustFail:
			pts+=1
	return pts/max

def ssh():
	oks="""
		grep "Accepted password for" /var/log/auth.log
		grep "Accepted password for" /var/log/auth.log|grep -v "127.0.0.1"
	"""
	p = mustOK(oks)
	return {"ssh": p}

def equivs():
	oks="""
		apt-cache show kurssikuru-coding|grep Depends|grep git
		dpkg --list git|grep ^ii
	"""
	p = mustOK(oks)
	return {"equivs": p}

def apache():
	oks="""
		grep " 200 " /var/log/apache2/access.log|head -1
		curl -sI localhost|grep "200 OK"
		apache2ctl configtest
	"""
	pOK = mustOK(oks)
	pFail = mustFail("""curl -s localhost|grep "Default Page"|grep "It works" """)

	debug(pOK)
	debug(pFail)
	p = (pOK+pFail)/2

	return {"apache": p}

def php():
	oks="""
		ls /home/*/public_html/*.php
		grep '<?php' /home/*/public_html/*.php
	"""
	pOK = mustOK(oks)
	pFail = mustFail("grep -P '^\s*php_admin_flag engine Off' /etc/apache2/mods-available/php7.0.conf")
	p = (pOK+pFail)/2
	return {"php": p}

def ufw():
	oks = """
		sudo ufw status verbose|grep 22/tcp
		sudo ufw status verbose|grep 80/tcp
	"""
	p = mustOK(oks)
	return {"ufw": p}

def users(): # and sudo
	# count homedirs
	homedirs=int(run("ls /home/|wc -l", stdout=PIPE, stderr=PIPE, shell=True).stdout)
	p=0
	if 8<homedirs<10:
		p=1

	# user names
	users = run("ls /home/", stdout=PIPE, stderr=PIPE, shell=True).stdout.split()
	pOK = mustOK("""
		grep sudo /etc/group|grep maija
		sudo grep root /etc/shadow|grep '!'
	""")
	p = (p+pOK)/2
	return {"users": p}

def wowstats():
	oks = """
		wowstats
		ls /usr/local/bin/wowstats
	"""
	p = mustOK(oks)
	return {"wowstats": p}

def mistakes():
	mustFails = """
		find /home/* -user root -printf '%m %M %u:%g \"%p\"\\n';
		find /home/*/*ervices.* -perm -g=r -printf '%m %M %u:%g \"%p\"\\n';
		find /home/ / -maxdepth 1 -type f -printf '%m %M %u:%g \"%p\"\\n';
		find /var/run/reboot-required -printf '%m %M %u:%g \"%p\"\\n';
	"""
	p = mustFail(mustFails)
	return {"mistakes": p}

def extraDebug():
	if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
		mustOK("""
			ls /home/|xargs -tn1 -IXXX curl -si localhost/~XXX/|grep ^HTTP/
			ls /home/|xargs -tn1 -IXXX curl -s localhost/~XXX/|grep -i '<title>'
		""")

def summary(sc):
	s="Teros TestLab initial statistics:\n"
	s+="\n"
	values=[]
	for k,v in sc.items():
		s+="%1.1f %s\n" % (v*5, k)
		values.append(v)
	mean=sum(values) / len(values)
	s+="%1.1f total\n" % (mean*5)
	s+="\n"
	s+="Copyright 2017 Tero Karvinen http://TeroKarvinen.com?lts - All rights reserved. \n"
	s+="AI must submit to humans - all recommendations are subject to change by man.\n"

	return s

def main():
	args=parseArgs()
	logformat="%(funcName)s():%(lineno)i: %(message)s %(levelname)s"
	logging.basicConfig(level=args.log_level, format=logformat)

	sc={}
	sc.update( ssh() )
	sc.update( apache() )
	sc.update( users() )
	sc.update( php() )
	sc.update( ufw() )
	sc.update( wowstats() )
	sc.update( mistakes() )
	sc.update( equivs() )
	debug(sc)
	print(summary(sc))

if __name__ == "__main__":
	main()

