mirror of
https://github.com/pi-hole/pi-hole
synced 2024-12-21 22:38:08 +00:00
* add test for file permissions of $webroot Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * changes sudo to su for running command as user www-data Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * installs PIHOLE_WEB_DEPS to create LIGHTTPD_USER Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * changes stdout to rc Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * use installPihole instead of installPiholeWeb in test Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * try installation process with main Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * mock systemctl Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * removes stickler errors Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * start lighttpd and make webpage test optional Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * test all files and directories in $webroot Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * fix stickler and codefactor warnings Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * set permission for /var/cache if it did not exist before Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * add test case for pihole files Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * fix stickler errors Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * revert "set permission for /var/cache if it did not exist before" and make lighttpd start work Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * add --add-cap=NET_ADMIN to enable FTL start Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * specify DNS server for cURL Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * check files created by FTL Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * reorder code and change nameserver in /etc/resolv.conf Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * resolve with dig instead of relying on /etc/resolv.conf Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * set IP to 127.0.0.1 in setupVars.conf for blockpage tests Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * resolve domain with dig and remove debug output Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * fix stickler errors Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * no git pull in Github Action runs for pull requests Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * --cap-add=ALL test Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * fix stickler errors Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * remove debug code Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * update_repo patch for CentOS 7 in Github Actions Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * removes TODOs and stickler warnings Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * adds trailing slash to domain Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * use only first result from dig Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * domain name resolution does not work reliably in docker container Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * repair executable permission Signed-off-by: pvogt09 <50047961+pvogt09@users.noreply.github.com> * Create mock_command_passthrough that allows intercepting of specific arguments - everything else is passed through to the proper command. Use this new command instead of making changes in basic-install.sh to make the tests pass. Signed-off-by: Adam Warner <me@adamwarner.co.uk> Co-authored-by: Adam Warner <me@adamwarner.co.uk>
This commit is contained in:
parent
ac4a975be5
commit
cedd1a2591
@ -64,7 +64,7 @@ def args(request):
|
|||||||
'''
|
'''
|
||||||
-t became required when tput began being used
|
-t became required when tput began being used
|
||||||
'''
|
'''
|
||||||
return '-t -d'
|
return '-t -d --cap-add=ALL'
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=[
|
@pytest.fixture(params=[
|
||||||
@ -100,7 +100,7 @@ def mock_command(script, args, container):
|
|||||||
in unit tests
|
in unit tests
|
||||||
'''
|
'''
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = '/usr/local/bin/{}'.format(script)
|
||||||
mock_script = dedent('''\
|
mock_script = dedent(r'''\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1" in'''.format(script=script))
|
case "\$1" in'''.format(script=script))
|
||||||
@ -121,13 +121,75 @@ def mock_command(script, args, container):
|
|||||||
scriptlog=script))
|
scriptlog=script))
|
||||||
|
|
||||||
|
|
||||||
|
def mock_command_passthrough(script, args, container):
|
||||||
|
'''
|
||||||
|
Per other mock_command* functions, allows intercepting of commands we don't want to run for real
|
||||||
|
in unit tests, however also allows only specific arguments to be mocked. Anything not defined will
|
||||||
|
be passed through to the actual command.
|
||||||
|
|
||||||
|
Example use-case: mocking `git pull` but still allowing `git clone` to work as intended
|
||||||
|
'''
|
||||||
|
orig_script_path = check_output('which {}'.format(script))
|
||||||
|
full_script_path = '/usr/local/bin/{}'.format(script)
|
||||||
|
mock_script = dedent(r'''\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1" in'''.format(script=script))
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent('''
|
||||||
|
{arg})
|
||||||
|
echo {res}
|
||||||
|
exit {retcode}
|
||||||
|
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent(r'''
|
||||||
|
*)
|
||||||
|
{orig_script_path} "\$@"
|
||||||
|
;;'''.format(orig_script_path=orig_script_path))
|
||||||
|
mock_script += dedent('''
|
||||||
|
esac''')
|
||||||
|
container.run('''
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
||||||
|
content=mock_script,
|
||||||
|
scriptlog=script))
|
||||||
|
|
||||||
|
|
||||||
|
def mock_command_run(script, args, container):
|
||||||
|
'''
|
||||||
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
|
in unit tests
|
||||||
|
'''
|
||||||
|
full_script_path = '/usr/local/bin/{}'.format(script)
|
||||||
|
mock_script = dedent(r'''\
|
||||||
|
#!/bin/bash -e
|
||||||
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
|
case "\$1 \$2" in'''.format(script=script))
|
||||||
|
for k, v in args.items():
|
||||||
|
case = dedent('''
|
||||||
|
\"{arg}\")
|
||||||
|
echo {res}
|
||||||
|
exit {retcode}
|
||||||
|
;;'''.format(arg=k, res=v[0], retcode=v[1]))
|
||||||
|
mock_script += case
|
||||||
|
mock_script += dedent('''
|
||||||
|
esac''')
|
||||||
|
container.run('''
|
||||||
|
cat <<EOF> {script}\n{content}\nEOF
|
||||||
|
chmod +x {script}
|
||||||
|
rm -f /var/log/{scriptlog}'''.format(script=full_script_path,
|
||||||
|
content=mock_script,
|
||||||
|
scriptlog=script))
|
||||||
|
|
||||||
|
|
||||||
def mock_command_2(script, args, container):
|
def mock_command_2(script, args, container):
|
||||||
'''
|
'''
|
||||||
Allows for setup of commands we don't really want to have to run for real
|
Allows for setup of commands we don't really want to have to run for real
|
||||||
in unit tests
|
in unit tests
|
||||||
'''
|
'''
|
||||||
full_script_path = '/usr/local/bin/{}'.format(script)
|
full_script_path = '/usr/local/bin/{}'.format(script)
|
||||||
mock_script = dedent('''\
|
mock_script = dedent(r'''\
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
echo "\$0 \$@" >> /var/log/{script}
|
echo "\$0 \$@" >> /var/log/{script}
|
||||||
case "\$1 \$2" in'''.format(script=script))
|
case "\$1 \$2" in'''.format(script=script))
|
||||||
@ -147,7 +209,6 @@ def mock_command_2(script, args, container):
|
|||||||
content=mock_script,
|
content=mock_script,
|
||||||
scriptlog=script))
|
scriptlog=script))
|
||||||
|
|
||||||
|
|
||||||
def run_script(Pihole, script):
|
def run_script(Pihole, script):
|
||||||
result = Pihole.run(script)
|
result = Pihole.run(script)
|
||||||
assert result.rc == 0
|
assert result.rc == 0
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
import re
|
import re
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
@ -6,7 +7,9 @@ from .conftest import (
|
|||||||
info_box,
|
info_box,
|
||||||
cross_box,
|
cross_box,
|
||||||
mock_command,
|
mock_command,
|
||||||
|
mock_command_run,
|
||||||
mock_command_2,
|
mock_command_2,
|
||||||
|
mock_command_passthrough,
|
||||||
run_script
|
run_script
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,6 +112,7 @@ def test_installPiholeWeb_fresh_install_no_errors(Pihole):
|
|||||||
confirms all web page assets from Core repo are installed on a fresh build
|
confirms all web page assets from Core repo are installed on a fresh build
|
||||||
'''
|
'''
|
||||||
installWeb = Pihole.run('''
|
installWeb = Pihole.run('''
|
||||||
|
umask 0027
|
||||||
source /opt/pihole/basic-install.sh
|
source /opt/pihole/basic-install.sh
|
||||||
installPiholeWeb
|
installPiholeWeb
|
||||||
''')
|
''')
|
||||||
@ -129,6 +133,516 @@ def test_installPiholeWeb_fresh_install_no_errors(Pihole):
|
|||||||
assert 'blockingpage.css' in web_directory
|
assert 'blockingpage.css' in web_directory
|
||||||
|
|
||||||
|
|
||||||
|
def get_directories_recursive(Pihole, directory):
|
||||||
|
if directory is None:
|
||||||
|
return directory
|
||||||
|
ls = Pihole.run('ls -d {}'.format(directory + '/*/'))
|
||||||
|
directories = list(filter(bool, ls.stdout.splitlines()))
|
||||||
|
dirs = directories
|
||||||
|
for dirval in directories:
|
||||||
|
dir_rec = get_directories_recursive(Pihole, dirval)
|
||||||
|
if isinstance(dir_rec, str):
|
||||||
|
dirs.extend([dir_rec])
|
||||||
|
else:
|
||||||
|
dirs.extend(dir_rec)
|
||||||
|
return dirs
|
||||||
|
|
||||||
|
|
||||||
|
def test_installPihole_fresh_install_readableFiles(Pihole):
|
||||||
|
'''
|
||||||
|
confirms all neccessary files are readable by pihole user
|
||||||
|
'''
|
||||||
|
# Whiptail dialog returns Cancel for user prompt
|
||||||
|
mock_command('whiptail', {'*': ('', '0')}, Pihole)
|
||||||
|
# mock git pull
|
||||||
|
mock_command_passthrough('git', {'pull': ('', '0')}, Pihole)
|
||||||
|
# mock systemctl to not start lighttpd and FTL
|
||||||
|
mock_command_2(
|
||||||
|
'systemctl',
|
||||||
|
{
|
||||||
|
'enable lighttpd': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'restart lighttpd': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'start lighttpd': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'enable pihole-FTL': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'restart pihole-FTL': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'start pihole-FTL': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'*': (
|
||||||
|
'echo "systemctl call with $@"',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Pihole
|
||||||
|
)
|
||||||
|
# try to install man
|
||||||
|
Pihole.run('command -v apt-get > /dev/null && apt-get install -qq man')
|
||||||
|
Pihole.run('command -v dnf > /dev/null && dnf install -y man')
|
||||||
|
Pihole.run('command -v yum > /dev/null && yum install -y man')
|
||||||
|
# create configuration file
|
||||||
|
setup_var_file = 'cat <<EOF> /etc/pihole/setupVars.conf\n'
|
||||||
|
for k, v in SETUPVARS.items():
|
||||||
|
setup_var_file += "{}={}\n".format(k, v)
|
||||||
|
setup_var_file += "INSTALL_WEB_SERVER=true\n"
|
||||||
|
setup_var_file += "INSTALL_WEB_INTERFACE=true\n"
|
||||||
|
setup_var_file += "EOF\n"
|
||||||
|
Pihole.run(setup_var_file)
|
||||||
|
install = Pihole.run('''
|
||||||
|
export TERM=xterm
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
umask 0027
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
source /opt/pihole/basic-install.sh > /dev/null
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
main
|
||||||
|
''')
|
||||||
|
assert 0 == install.rc
|
||||||
|
maninstalled = True
|
||||||
|
if (info_box + ' man not installed') in install.stdout:
|
||||||
|
maninstalled = False
|
||||||
|
piholeuser = 'pihole'
|
||||||
|
exit_status_success = 0
|
||||||
|
test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}'
|
||||||
|
# check files in /etc/pihole for read, write and execute permission
|
||||||
|
check_etc = test_cmd.format('r', '/etc/pihole', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_etc).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_etc = test_cmd.format('x', '/etc/pihole', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_etc).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable and writable dhcp.leases
|
||||||
|
check_leases = test_cmd.format('r', '/etc/pihole/dhcp.leases', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_leases).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_leases = test_cmd.format('w', '/etc/pihole/dhcp.leases', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_leases).rc
|
||||||
|
# readable dns-servers.conf
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_servers = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/dns-servers.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_servers).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable GitHubVersions
|
||||||
|
check_version = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/GitHubVersions', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_version).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable install.log
|
||||||
|
check_install = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/install.log', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_install).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable localbranches
|
||||||
|
check_localbranch = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/localbranches', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_localbranch).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable localversions
|
||||||
|
check_localversion = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/localversions', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_localversion).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable logrotate
|
||||||
|
check_logrotate = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/logrotate', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_logrotate).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable macvendor.db
|
||||||
|
check_macvendor = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/macvendor.db', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_macvendor).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable and writeable pihole-FTL.conf
|
||||||
|
check_FTLconf = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/pihole-FTL.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_FTLconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_FTLconf = test_cmd.format(
|
||||||
|
'w', '/etc/pihole/pihole-FTL.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_FTLconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable setupVars.conf
|
||||||
|
check_setup = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/setupVars.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_setup).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check dnsmasq files
|
||||||
|
# readable /etc/dnsmasq.conf
|
||||||
|
check_dnsmasqconf = test_cmd.format(
|
||||||
|
'r', '/etc/dnsmasq.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_dnsmasqconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# readable /etc/dnsmasq.d/01-pihole.conf
|
||||||
|
check_dnsmasqconf = test_cmd.format(
|
||||||
|
'r', '/etc/dnsmasq.d', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_dnsmasqconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_dnsmasqconf = test_cmd.format(
|
||||||
|
'x', '/etc/dnsmasq.d', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_dnsmasqconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_dnsmasqconf = test_cmd.format(
|
||||||
|
'r', '/etc/dnsmasq.d/01-pihole.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_dnsmasqconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check readable and executable /etc/init.d/pihole-FTL
|
||||||
|
check_init = test_cmd.format(
|
||||||
|
'x', '/etc/init.d/pihole-FTL', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_init).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_init = test_cmd.format(
|
||||||
|
'r', '/etc/init.d/pihole-FTL', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_init).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check readable /etc/lighttpd/lighttpd.conf
|
||||||
|
check_lighttpd = test_cmd.format(
|
||||||
|
'r', '/etc/lighttpd/lighttpd.conf', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_lighttpd).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check readable and executable manpages
|
||||||
|
if maninstalled is True:
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'x', '/usr/local/share/man', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'x', '/usr/local/share/man/man8', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man/man8', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'x', '/usr/local/share/man/man5', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man/man5', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man/man8/pihole.8', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man/man8/pihole-FTL.8', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_man = test_cmd.format(
|
||||||
|
'r', '/usr/local/share/man/man5/pihole-FTL.conf.5', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_man).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check not readable sudoers file
|
||||||
|
check_sudo = test_cmd.format(
|
||||||
|
'r', '/etc/sudoers.d/pihole', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_sudo).rc
|
||||||
|
assert exit_status_success != actual_rc
|
||||||
|
# check not readable cron file
|
||||||
|
check_sudo = test_cmd.format(
|
||||||
|
'x', '/etc/cron.d/', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_sudo = test_cmd.format(
|
||||||
|
'r', '/etc/cron.d/', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_sudo = test_cmd.format(
|
||||||
|
'r', '/etc/cron.d/pihole', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_sudo).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
directories = get_directories_recursive(Pihole, '/etc/.pihole/')
|
||||||
|
for directory in directories:
|
||||||
|
check_pihole = test_cmd.format('r', directory, piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
check_pihole = test_cmd.format('x', directory, piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
findfiles = 'find "{}" -maxdepth 1 -type f -exec echo {{}} \\;;'
|
||||||
|
filelist = Pihole.run(findfiles.format(directory))
|
||||||
|
files = list(filter(bool, filelist.stdout.splitlines()))
|
||||||
|
for file in files:
|
||||||
|
check_pihole = test_cmd.format('r', file, piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_webpage", [True])
|
||||||
|
def test_installPihole_fresh_install_readableBlockpage(Pihole, test_webpage):
|
||||||
|
'''
|
||||||
|
confirms all web page assets from Core repo are readable
|
||||||
|
by $LIGHTTPD_USER on a fresh build
|
||||||
|
'''
|
||||||
|
piholeWebpage = [
|
||||||
|
"127.0.0.1",
|
||||||
|
# "pi.hole"
|
||||||
|
]
|
||||||
|
# Whiptail dialog returns Cancel for user prompt
|
||||||
|
mock_command('whiptail', {'*': ('', '0')}, Pihole)
|
||||||
|
# mock git pull
|
||||||
|
mock_command_passthrough('git', {'pull': ('', '0')}, Pihole)
|
||||||
|
# mock systemctl to start lighttpd and FTL
|
||||||
|
ligthttpdcommand = dedent(r'''\"\"
|
||||||
|
echo 'starting lighttpd with {}'
|
||||||
|
if [ command -v "apt-get" >/dev/null 2>&1 ]; then
|
||||||
|
LIGHTTPD_USER="www-data"
|
||||||
|
LIGHTTPD_GROUP="www-data"
|
||||||
|
else
|
||||||
|
LIGHTTPD_USER="lighttpd"
|
||||||
|
LIGHTTPD_GROUP="lighttpd"
|
||||||
|
fi
|
||||||
|
mkdir -p "{run}"
|
||||||
|
chown {usergroup} "{run}"
|
||||||
|
mkdir -p "{cache}"
|
||||||
|
chown {usergroup} "/var/cache"
|
||||||
|
chown {usergroup} "{cache}"
|
||||||
|
mkdir -p "{compress}"
|
||||||
|
chown {usergroup} "{compress}"
|
||||||
|
mkdir -p "{uploads}"
|
||||||
|
chown {usergroup} "{uploads}"
|
||||||
|
chmod 0777 /var
|
||||||
|
chmod 0777 /var/cache
|
||||||
|
chmod 0777 "{cache}"
|
||||||
|
find "{run}" -type d -exec chmod 0777 {chmodarg} \;;
|
||||||
|
find "{run}" -type f -exec chmod 0666 {chmodarg} \;;
|
||||||
|
find "{compress}" -type d -exec chmod 0777 {chmodarg} \;;
|
||||||
|
find "{compress}" -type f -exec chmod 0666 {chmodarg} \;;
|
||||||
|
find "{uploads}" -type d -exec chmod 0777 {chmodarg} \;;
|
||||||
|
find "{uploads}" -type f -exec chmod 0666 {chmodarg} \;;
|
||||||
|
/usr/sbin/lighttpd -tt -f '{config}'
|
||||||
|
/usr/sbin/lighttpd -f '{config}'
|
||||||
|
echo \"\"'''.format(
|
||||||
|
'{}',
|
||||||
|
usergroup='${{LIGHTTPD_USER}}:${{LIGHTTPD_GROUP}}',
|
||||||
|
chmodarg='{{}}',
|
||||||
|
config='/etc/lighttpd/lighttpd.conf',
|
||||||
|
run='/var/run/lighttpd',
|
||||||
|
cache='/var/cache/lighttpd',
|
||||||
|
uploads='/var/cache/lighttpd/uploads',
|
||||||
|
compress='/var/cache/lighttpd/compress'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FTLcommand = dedent('''\"\"
|
||||||
|
set -x
|
||||||
|
/etc/init.d/pihole-FTL restart
|
||||||
|
echo \"\"''')
|
||||||
|
mock_command_run(
|
||||||
|
'systemctl',
|
||||||
|
{
|
||||||
|
'enable lighttpd': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'restart lighttpd': (
|
||||||
|
ligthttpdcommand.format('restart'),
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'start lighttpd': (
|
||||||
|
ligthttpdcommand.format('start'),
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'enable pihole-FTL': (
|
||||||
|
'',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'restart pihole-FTL': (
|
||||||
|
FTLcommand,
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'start pihole-FTL': (
|
||||||
|
FTLcommand,
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
'*': (
|
||||||
|
'echo "systemctl call with $@"',
|
||||||
|
'0'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Pihole
|
||||||
|
)
|
||||||
|
# create configuration file
|
||||||
|
setup_var_file = 'cat <<EOF> /etc/pihole/setupVars.conf\n'
|
||||||
|
for k, v in SETUPVARS.items():
|
||||||
|
setup_var_file += "{}={}\n".format(k, v)
|
||||||
|
setup_var_file += "INSTALL_WEB_SERVER=true\n"
|
||||||
|
setup_var_file += "INSTALL_WEB_INTERFACE=true\n"
|
||||||
|
setup_var_file += "IPV4_ADDRESS=127.0.0.1\n"
|
||||||
|
setup_var_file += "EOF\n"
|
||||||
|
Pihole.run(setup_var_file)
|
||||||
|
installWeb = Pihole.run('''
|
||||||
|
export TERM=xterm
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
umask 0027
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
source /opt/pihole/basic-install.sh > /dev/null
|
||||||
|
runUnattended=true
|
||||||
|
useUpdateVars=true
|
||||||
|
main
|
||||||
|
echo "LIGHTTPD_USER=${LIGHTTPD_USER}"
|
||||||
|
echo "webroot=${webroot}"
|
||||||
|
echo "INSTALL_WEB_INTERFACE=${INSTALL_WEB_INTERFACE}"
|
||||||
|
echo "INSTALL_WEB_SERVER=${INSTALL_WEB_SERVER}"
|
||||||
|
''')
|
||||||
|
assert 0 == installWeb.rc
|
||||||
|
piholeuser = 'pihole'
|
||||||
|
webuser = ''
|
||||||
|
user = re.findall(
|
||||||
|
r"^\s*LIGHTTPD_USER=.*$", installWeb.stdout, re.MULTILINE)
|
||||||
|
for match in user:
|
||||||
|
webuser = match.replace('LIGHTTPD_USER=', '').strip()
|
||||||
|
webroot = ''
|
||||||
|
user = re.findall(
|
||||||
|
r"^\s*webroot=.*$", installWeb.stdout, re.MULTILINE)
|
||||||
|
for match in user:
|
||||||
|
webroot = match.replace('webroot=', '').strip()
|
||||||
|
if not webroot.strip():
|
||||||
|
webroot = '/var/www/html'
|
||||||
|
installWebInterface = True
|
||||||
|
interface = re.findall(
|
||||||
|
r"^\s*INSTALL_WEB_INTERFACE=.*$", installWeb.stdout, re.MULTILINE)
|
||||||
|
for match in interface:
|
||||||
|
testvalue = match.replace('INSTALL_WEB_INTERFACE=', '').strip().lower()
|
||||||
|
if not testvalue.strip():
|
||||||
|
installWebInterface = testvalue == "true"
|
||||||
|
installWebServer = True
|
||||||
|
server = re.findall(
|
||||||
|
r"^\s*INSTALL_WEB_SERVER=.*$", installWeb.stdout, re.MULTILINE)
|
||||||
|
for match in server:
|
||||||
|
testvalue = match.replace('INSTALL_WEB_SERVER=', '').strip().lower()
|
||||||
|
if not testvalue.strip():
|
||||||
|
installWebServer = testvalue == "true"
|
||||||
|
# if webserver install was not requested
|
||||||
|
# at least pihole must be able to read files
|
||||||
|
if installWebServer is False:
|
||||||
|
webuser = piholeuser
|
||||||
|
exit_status_success = 0
|
||||||
|
test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}'
|
||||||
|
# check files that need a running FTL to be created
|
||||||
|
# readable and writeable pihole-FTL.db
|
||||||
|
check_FTLconf = test_cmd.format(
|
||||||
|
'r', '/etc/pihole/pihole-FTL.db', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_FTLconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_FTLconf = test_cmd.format(
|
||||||
|
'w', '/etc/pihole/pihole-FTL.db', piholeuser)
|
||||||
|
actual_rc = Pihole.run(check_FTLconf).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check directories above $webroot for read and execute permission
|
||||||
|
check_var = test_cmd.format('r', '/var', webuser)
|
||||||
|
actual_rc = Pihole.run(check_var).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_var = test_cmd.format('x', '/var', webuser)
|
||||||
|
actual_rc = Pihole.run(check_var).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_www = test_cmd.format('r', '/var/www', webuser)
|
||||||
|
actual_rc = Pihole.run(check_www).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_www = test_cmd.format('x', '/var/www', webuser)
|
||||||
|
actual_rc = Pihole.run(check_www).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_html = test_cmd.format('r', '/var/www/html', webuser)
|
||||||
|
actual_rc = Pihole.run(check_html).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_html = test_cmd.format('x', '/var/www/html', webuser)
|
||||||
|
actual_rc = Pihole.run(check_html).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check directories below $webroot for read and execute permission
|
||||||
|
check_admin = test_cmd.format('r', webroot + '/admin', webuser)
|
||||||
|
actual_rc = Pihole.run(check_admin).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_admin = test_cmd.format('x', webroot + '/admin', webuser)
|
||||||
|
actual_rc = Pihole.run(check_admin).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
directories = get_directories_recursive(Pihole, webroot + '/admin/*/')
|
||||||
|
for directory in directories:
|
||||||
|
check_pihole = test_cmd.format('r', directory, webuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
check_pihole = test_cmd.format('x', directory, webuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
findfiles = 'find "{}" -maxdepth 1 -type f -exec echo {{}} \\;;'
|
||||||
|
filelist = Pihole.run(findfiles.format(directory))
|
||||||
|
files = list(filter(bool, filelist.stdout.splitlines()))
|
||||||
|
for file in files:
|
||||||
|
check_pihole = test_cmd.format('r', file, webuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
# check web interface files
|
||||||
|
# change nameserver to pi-hole
|
||||||
|
# setting nameserver in /etc/resolv.conf to pi-hole does
|
||||||
|
# not work here because of the way docker uses this file
|
||||||
|
ns = Pihole.run(
|
||||||
|
r"sed -i 's/nameserver.*/nameserver 127.0.0.1/' /etc/resolv.conf")
|
||||||
|
pihole_is_ns = ns.rc == 0
|
||||||
|
|
||||||
|
def is_ip(address):
|
||||||
|
m = re.match(r"(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})", address)
|
||||||
|
return bool(m)
|
||||||
|
if installWebInterface is True:
|
||||||
|
check_pihole = test_cmd.format('r', webroot + '/pihole', webuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_pihole = test_cmd.format('x', webroot + '/pihole', webuser)
|
||||||
|
actual_rc = Pihole.run(check_pihole).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
# check most important files in $webroot for read permission
|
||||||
|
check_index = test_cmd.format(
|
||||||
|
'r', webroot + '/pihole/index.php', webuser)
|
||||||
|
actual_rc = Pihole.run(check_index).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
check_blockpage = test_cmd.format(
|
||||||
|
'r', webroot + '/pihole/blockingpage.css', webuser)
|
||||||
|
actual_rc = Pihole.run(check_blockpage).rc
|
||||||
|
assert exit_status_success == actual_rc
|
||||||
|
if test_webpage is True:
|
||||||
|
# check webpage for unreadable files
|
||||||
|
noPHPfopen = re.compile(
|
||||||
|
(r"PHP Error(%d+):\s+fopen([^)]+):\s+" +
|
||||||
|
r"failed to open stream: " +
|
||||||
|
r"Permission denied in"),
|
||||||
|
re.I)
|
||||||
|
# using cURL option --dns-servers is not possible
|
||||||
|
status = (
|
||||||
|
'curl -s --head "{}" | ' +
|
||||||
|
'head -n 1 | ' +
|
||||||
|
'grep "HTTP/1.[01] [23].." > /dev/null')
|
||||||
|
digcommand = r"dig A +short {} @127.0.0.1 | head -n 1"
|
||||||
|
pagecontent = 'curl --verbose -L "{}"'
|
||||||
|
for page in piholeWebpage:
|
||||||
|
testpage = "http://" + page + "/admin/"
|
||||||
|
resolvesuccess = True
|
||||||
|
if is_ip(page) is False:
|
||||||
|
dig = Pihole.run(digcommand.format(page))
|
||||||
|
testpage = "http://" + dig.stdout.strip() + "/admin/"
|
||||||
|
resolvesuccess = dig.rc == 0
|
||||||
|
if resolvesuccess or pihole_is_ns:
|
||||||
|
# check HTTP status of blockpage
|
||||||
|
actual_rc = Pihole.run(status.format(testpage))
|
||||||
|
assert exit_status_success == actual_rc.rc
|
||||||
|
# check for PHP error
|
||||||
|
actual_output = Pihole.run(pagecontent.format(testpage))
|
||||||
|
assert noPHPfopen.match(actual_output.stdout) is None
|
||||||
|
|
||||||
|
|
||||||
def test_update_package_cache_success_no_errors(Pihole):
|
def test_update_package_cache_success_no_errors(Pihole):
|
||||||
'''
|
'''
|
||||||
confirms package cache was updated without any errors
|
confirms package cache was updated without any errors
|
||||||
|
Loading…
Reference in New Issue
Block a user