From f9d990145a9b52fab61ff80b40182f3e94d724fe Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 30 May 2022 03:00:16 -0300 Subject: [PATCH 01/18] Always use WEBPASSWORD env var if set Signed-off-by: RD WebDesign --- bash_functions.sh | 34 +++++++++++++++++++++++----------- start.sh | 4 ++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/bash_functions.sh b/bash_functions.sh index 38264ee..a2791a7 100644 --- a/bash_functions.sh +++ b/bash_functions.sh @@ -6,12 +6,12 @@ fix_capabilities() { # Testing on Docker 20.10.14 with no caps set shows the following caps available to the container: # Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep # FTL can also use CAP_NET_ADMIN and CAP_SYS_NICE. If we try to set them when they haven't been explicitly enabled, FTL will not start. Test for them first: - + /sbin/capsh --has-p=cap_chown && CAP_STR+=',CAP_CHOWN' /sbin/capsh --has-p=cap_net_bind_service && CAP_STR+=',CAP_NET_BIND_SERVICE' /sbin/capsh --has-p=cap_net_raw && CAP_STR+=',CAP_NET_RAW' /sbin/capsh --has-p=cap_net_admin && CAP_STR+=',CAP_NET_ADMIN' || DHCP_READY='false' - /sbin/capsh --has-p=cap_sys_nice && CAP_STR+=',CAP_SYS_NICE' + /sbin/capsh --has-p=cap_sys_nice && CAP_STR+=',CAP_SYS_NICE' if [[ ${CAP_STR} ]]; then # We have the (some of) the above caps available to us - apply them to pihole-FTL @@ -24,12 +24,12 @@ fix_capabilities() { DHCP_ACTIVE='false' change_setting "DHCP_ACTIVE" "false" fi - + if [[ $ret -ne 0 && "${DNSMASQ_USER:-pihole}" != "root" ]]; then echo "ERROR: Unable to set capabilities for pihole-FTL. Cannot run as non-root." echo " If you are seeing this error, please set the environment variable 'DNSMASQ_USER' to the value 'root'" exit 1 - fi + fi else echo "WARNING: Unable to set capabilities for pihole-FTL." echo " Please ensure that the container has the required capabilities." @@ -45,21 +45,21 @@ prepare_configs() { LIGHTTPD_GROUP="www-data" LIGHTTPD_CFG="lighttpd.conf.debian" installConfigs - + if [ ! -f "${setupVars}" ]; then install -m 644 /dev/null "${setupVars}" echo "Creating empty ${setupVars} file." fi - + set +e mkdir -p /var/run/pihole /var/log/pihole - + chown pihole:root /etc/lighttpd - + # In case of `pihole` UID being changed, re-chown the pihole scripts and pihole command chown -R pihole:root "${PI_HOLE_INSTALL_DIR}" chown pihole:root "${PI_HOLE_BIN_DIR}/pihole" - + set -e # Update version numbers pihole updatechecker @@ -279,9 +279,21 @@ generate_password() { } setup_web_password() { - setup_var_exists "WEBPASSWORD" && return + if [ -z "${WEBPASSWORD+x}" ] ; then + # ENV WEBPASSWORD is not set + + # Exit if setupvars already has a password + setup_var_exists "WEBPASSWORD" && return + + # Generate new password + generate_password + else + # ENV WEBPASSWORD is set an will be used + echo "Assigning password defined by Environment Variable" + fi + + PASS="$WEBPASSWORD" - PASS="$1" # Explicitly turn off bash printing when working with secrets { set +x; } 2>/dev/null diff --git a/start.sh b/start.sh index 90ef9c3..8994d39 100755 --- a/start.sh +++ b/start.sh @@ -39,6 +39,7 @@ export PIHOLE_DOMAIN export DHCP_IPv6 export DHCP_rapid_commit export WEBTHEME +export WEBPASSWORD export CUSTOM_CACHE_SIZE export adlistFile='/etc/pihole/adlists.list' @@ -67,7 +68,6 @@ echo " ::: Starting docker specific checks & setup for docker pihole/pihole" fix_capabilities load_web_password_secret -generate_password validate_env || exit 1 prepare_configs @@ -185,7 +185,7 @@ fi [[ -n "${DHCP_ACTIVE}" && ${DHCP_ACTIVE} == "true" ]] && echo "Setting DHCP server" && setup_dhcp setup_web_port "$WEB_PORT" -setup_web_password "$WEBPASSWORD" +setup_web_password setup_temp_unit "$TEMPERATUREUNIT" setup_ui_layout "$WEBUIBOXEDLAYOUT" setup_admin_email "$ADMIN_EMAIL" From 67fc9251535dd2bb218bbd28ec2f8dab7ca74328 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 30 May 2022 17:31:57 -0300 Subject: [PATCH 02/18] Using the same format for the new message Signed-off-by: RD WebDesign --- bash_functions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bash_functions.sh b/bash_functions.sh index a2791a7..d6b1115 100644 --- a/bash_functions.sh +++ b/bash_functions.sh @@ -289,7 +289,7 @@ setup_web_password() { generate_password else # ENV WEBPASSWORD is set an will be used - echo "Assigning password defined by Environment Variable" + echo "::: Assigning password defined by Environment Variable" fi PASS="$WEBPASSWORD" From 6b9a4e6216244bcb3e1642f95181de3278417b1b Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 6 Jun 2022 20:12:24 +0100 Subject: [PATCH 03/18] Fix up tests to work with new logic Signed-off-by: Adam Warner --- bash_functions.sh | 13 ++++--------- test/test_bash_functions.py | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/bash_functions.sh b/bash_functions.sh index d6b1115..09dd7a7 100644 --- a/bash_functions.sh +++ b/bash_functions.sh @@ -270,13 +270,7 @@ load_web_password_secret() { fi; } -generate_password() { - if [ -z "${WEBPASSWORD+x}" ] ; then - # Not set at all, give the user a random pass - WEBPASSWORD=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8) - echo "Assigning random password: $WEBPASSWORD" - fi; -} + setup_web_password() { if [ -z "${WEBPASSWORD+x}" ] ; then @@ -285,8 +279,9 @@ setup_web_password() { # Exit if setupvars already has a password setup_var_exists "WEBPASSWORD" && return - # Generate new password - generate_password + # Generate new random password + WEBPASSWORD=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8) + echo "Assigning random password: $WEBPASSWORD" else # ENV WEBPASSWORD is set an will be used echo "::: Assigning password defined by Environment Variable" diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index 6929c2b..02d0bd8 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -180,7 +180,7 @@ def test_debian_setup_php_env(Docker, expected_lines, repeat_function): def test_webPassword_random_generation(Docker): ''' When a user sets webPassword env the admin password gets set to that ''' - function = Docker.run('. /bash_functions.sh ; eval `grep generate_password /start.sh`') + function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') assert 'assigning random password' in function.stdout.lower() @@ -203,11 +203,18 @@ def test_webPassword_env_assigns_password_to_file_or_removes_if_empty(Docker, ar @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize('test_args', ['-e WEBPASSWORD=login', '-e WEBPASSWORD=""']) -def test_webPassword_pre_existing_trumps_all_envs(Docker, args_env, test_args): - '''When a user setup webPassword in the volume prior to first container boot, - during prior container boot, the prior volume password is left intact / setup skipped''' - Docker.run('. /opt/pihole/webpage.sh ; add_setting WEBPASSWORD volumepass') +def test_env_always_updates_password(Docker, args_env, test_args): + '''When a user sets the WEBPASSWORD environment variable, ensure it always sets the password''' function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') - assert '::: Pre existing WEBPASSWORD found' in function.stdout + assert '::: Assigning password defined by Environment Variable' in function.stdout + + +@pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) +def test_setupvars_trumps_random_password_if_set(Docker, args_env, test_args): + '''If a password is already set in setupVars, and no password is set in the environment variable, do not generate a random password''' + Docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair /etc/pihole/setupVars.conf WEBPASSWORD volumepass') + function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') + + assert 'Pre existing WEBPASSWORD found' in function.stdout assert Docker.run('grep -q \'{}\' {}'.format('WEBPASSWORD=volumepass', '/etc/pihole/setupVars.conf')).rc == 0 From 64e449c133929aa6a23a13d617c685a09fed3017 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 6 Jun 2022 20:26:26 +0100 Subject: [PATCH 04/18] fix [this code smell](https://sonarcloud.io/project/issues?pullRequest=1106&issues=AYE6byrIbM3H9G6ifn9K&open=AYE6byrIbM3H9G6ifn9K&id=pi-hole_docker-pi-hole) Signed-off-by: Adam Warner --- test/test_bash_functions.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index 02d0bd8..9ab0b7e 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -178,9 +178,12 @@ def test_debian_setup_php_env(Docker, expected_lines, repeat_function): assert False, f'Found line {expected_line} times (more than once): {found_lines}' +WEBPASSWORD_TEST_FUNCTION_COMMAND='. /bash_functions.sh ; eval `grep setup_web_password /start.sh`' + + def test_webPassword_random_generation(Docker): ''' When a user sets webPassword env the admin password gets set to that ''' - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') + function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert 'assigning random password' in function.stdout.lower() @@ -191,7 +194,7 @@ def test_webPassword_random_generation(Docker): ]) def test_webPassword_env_assigns_password_to_file_or_removes_if_empty(Docker, args_env, secure, setupVarsHash): ''' When a user sets webPassword env the admin password gets set or removed if empty ''' - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') + function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) if secure: assert 'new password set' in function.stdout.lower() @@ -205,7 +208,7 @@ def test_webPassword_env_assigns_password_to_file_or_removes_if_empty(Docker, ar @pytest.mark.parametrize('test_args', ['-e WEBPASSWORD=login', '-e WEBPASSWORD=""']) def test_env_always_updates_password(Docker, args_env, test_args): '''When a user sets the WEBPASSWORD environment variable, ensure it always sets the password''' - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') + function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert '::: Assigning password defined by Environment Variable' in function.stdout @@ -214,7 +217,7 @@ def test_env_always_updates_password(Docker, args_env, test_args): def test_setupvars_trumps_random_password_if_set(Docker, args_env, test_args): '''If a password is already set in setupVars, and no password is set in the environment variable, do not generate a random password''' Docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair /etc/pihole/setupVars.conf WEBPASSWORD volumepass') - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`') + function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert 'Pre existing WEBPASSWORD found' in function.stdout assert Docker.run('grep -q \'{}\' {}'.format('WEBPASSWORD=volumepass', '/etc/pihole/setupVars.conf')).rc == 0 From b3717000aee7e2223778948b5e895e89b5d510dd Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 6 Jun 2022 21:25:20 +0100 Subject: [PATCH 05/18] Address Sonar rules S117 (https://rules.sonarsource.com/python/RSPEC-117) and S1542(https://rules.sonarsource.com/python/RSPEC-1542) in all test .py files Signed-off-by: Adam Warner --- test/conftest.py | 34 ++++++------ test/test_bash_functions.py | 104 ++++++++++++++++++------------------ test/test_pihole_scripts.py | 36 ++++++------- test/test_start.py | 26 ++++----- 4 files changed, 100 insertions(+), 100 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index c2cd667..ac7174b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -44,7 +44,7 @@ def test_args(): ''' test override fixture to provide arguments separate from our core args ''' return '' -def DockerGeneric(request, _test_args, _args, _image, _cmd, _entrypoint): +def docker_generic(request, _test_args, _args, _image, _cmd, _entrypoint): #assert 'docker' in check_output('id'), "Are you in the docker group?" # Always appended PYTEST arg to tell pihole we're testing if 'pihole' in _image and 'PYTEST=1' not in _args: @@ -67,17 +67,17 @@ def DockerGeneric(request, _test_args, _args, _image, _cmd, _entrypoint): @pytest.fixture -def Docker(request, test_args, args, image, cmd, entrypoint): +def docker(request, test_args, args, image, cmd, entrypoint): ''' One-off Docker container run ''' - return DockerGeneric(request, test_args, args, image, cmd, entrypoint) + return docker_generic(request, test_args, args, image, cmd, entrypoint) @pytest.fixture(scope='module') -def DockerPersist(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint, Dig): +def docker_persist(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint, dig): ''' Persistent Docker container for multiple tests, instead of stopping container after one test ''' ''' Uses DUP'd module scoped fixtures because smaller scoped fixtures won't mix with module scope ''' - persistent_container = DockerGeneric(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint) + persistent_container = docker_generic(request, persist_test_args, persist_args, persist_image, persist_cmd, persist_entrypoint) ''' attach a dig container for lookups ''' - persistent_container.dig = Dig(persistent_container.id) + persistent_container.dig = dig(persistent_container.id) return persistent_container @pytest.fixture @@ -171,12 +171,12 @@ def persist_entrypoint(): return '' @pytest.fixture -def Slow(): +def slow(): """ Run a slow check, check if the state is correct for `timeout` seconds. """ import time - def slow(check, timeout=20): + def _slow(check, timeout=20): timeout_at = time.time() + timeout while True: try: @@ -188,26 +188,26 @@ def Slow(): raise e else: return - return slow + return _slow @pytest.fixture(scope='module') -def Dig(): +def dig(): ''' separate container to link to pi-hole and perform lookups ''' ''' a docker pull is faster than running an install of dnsutils ''' - def dig(docker_id): + def _dig(docker_id): args = '--link {}:test_pihole'.format(docker_id) image = 'azukiapp/dig' cmd = 'tail -f /dev/null' - dig_container = DockerGeneric(request, '', args, image, cmd, '') + dig_container = docker_generic(request, '', args, image, cmd, '') return dig_container - return dig + return _dig ''' Persistent Docker container for testing service post start.sh ''' @pytest.fixture -def RunningPiHole(DockerPersist, Slow, persist_webserver): +def running_pihole(docker_persist, slow, persist_webserver): ''' Persist a fully started docker-pi-hole to help speed up subsequent tests ''' - Slow(lambda: DockerPersist.run('pgrep pihole-FTL').rc == 0) - Slow(lambda: DockerPersist.run('pgrep lighttpd').rc == 0) - return DockerPersist + slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) + slow(lambda: docker_persist.run('pgrep lighttpd').rc == 0) + return docker_persist diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index 9ab0b7e..451fcb7 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -10,32 +10,32 @@ import re ('-e "IPv6=False"', False, 'IPv4'), ('-e "IPv6=foobar"', False, 'IPv4'), ]) -def test_IPv6_not_True_removes_ipv6(Docker, Slow, test_args, expected_ipv6, expected_stdout): +def test_ipv6_not_true_removes_ipv6(docker, slow, test_args, expected_ipv6, expected_stdout): ''' When a user overrides IPv6=True they only get IPv4 listening webservers ''' IPV6_LINE = 'use-ipv6.pl' WEB_CONFIG = '/etc/lighttpd/lighttpd.conf' - function = Docker.run('. /bash_functions.sh ; setup_ipv4_ipv6') + function = docker.run('. /bash_functions.sh ; setup_ipv4_ipv6') assert "Using {}".format(expected_stdout) in function.stdout if expected_stdout == 'IPv4': assert 'IPv6' not in function.stdout # On overlay2(?) docker sometimes writes to disk are slow enough to break some tests... expected_ipv6_check = lambda: (\ - IPV6_LINE in Docker.run('grep \'use-ipv6.pl\' {}'.format(WEB_CONFIG)).stdout + IPV6_LINE in docker.run('grep \'use-ipv6.pl\' {}'.format(WEB_CONFIG)).stdout ) == expected_ipv6 - Slow(expected_ipv6_check) + slow(expected_ipv6_check) @pytest.mark.parametrize('test_args', ['-e "WEB_PORT=999"']) -def test_overrides_default_WEB_PORT(Docker, Slow, test_args): +def test_overrides_default_web_port(docker, slow, test_args): ''' When a --net=host user sets WEB_PORT to avoid synology's 80 default IPv4 and or IPv6 ports are updated''' CONFIG_LINE = r'server.port\s*=\s*999' WEB_CONFIG = '/etc/lighttpd/lighttpd.conf' - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_port /start.sh`') + function = docker.run('. /bash_functions.sh ; eval `grep setup_web_port /start.sh`') assert "Custom WEB_PORT set to 999" in function.stdout assert "INFO: Without proper router DNAT forwarding to 127.0.0.1:999, you may not get any blocked websites on ads" in function.stdout - Slow(lambda: re.search(CONFIG_LINE, Docker.run('cat {}'.format(WEB_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(WEB_CONFIG)).stdout) != None) @pytest.mark.parametrize('test_args,expected_error', [ @@ -43,42 +43,42 @@ def test_overrides_default_WEB_PORT(Docker, Slow, test_args): ('-e WEB_PORT="1,000"', 'WARNING: Custom WEB_PORT not used - 1,000 is not an integer'), ('-e WEB_PORT="99999"', 'WARNING: Custom WEB_PORT not used - 99999 is not within valid port range of 1-65535'), ]) -def test_bad_input_to_WEB_PORT(Docker, test_args, expected_error): - function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_port /start.sh`') +def test_bad_input_to_web_port(docker, test_args, expected_error): + function = docker.run('. /bash_functions.sh ; eval `grep setup_web_port /start.sh`') assert expected_error in function.stdout @pytest.mark.parametrize('test_args,cache_size', [('-e CUSTOM_CACHE_SIZE="0"', '0'), ('-e CUSTOM_CACHE_SIZE="20000"', '20000')]) -def test_overrides_default_CUSTOM_CACHE_SIZE(Docker, Slow, test_args, cache_size): +def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size): ''' Changes the cache_size setting to increase or decrease the cache size for dnsmasq''' CONFIG_LINE = r'cache-size\s*=\s*{}'.format(cache_size) DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' - function = Docker.run('echo ${CUSTOM_CACHE_SIZE};. ./bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_dnsmasq /start.sh`') + function = docker.run('echo ${CUSTOM_CACHE_SIZE};. ./bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_dnsmasq /start.sh`') assert "Custom CUSTOM_CACHE_SIZE set to {}".format(cache_size) in function.stdout - Slow(lambda: re.search(CONFIG_LINE, Docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) @pytest.mark.parametrize('test_args', [ '-e CUSTOM_CACHE_SIZE="-1"', '-e CUSTOM_CACHE_SIZE="1,000"', ]) -def test_bad_input_to_CUSTOM_CACHE_SIZE(Docker, Slow, test_args): +def test_bad_input_to_custom_cache_size(docker, slow, test_args): CONFIG_LINE = r'cache-size\s*=\s*10000' DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' - Docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') - Slow(lambda: re.search(CONFIG_LINE, Docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') + slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) @pytest.mark.parametrize('test_args', [ '-e DNSSEC="true" -e CUSTOM_CACHE_SIZE="0"', ]) -def test_dnssec_enabled_with_CUSTOM_CACHE_SIZE(Docker, Slow, test_args): +def test_dnssec_enabled_with_custom_cache_size(docker, slow, test_args): CONFIG_LINE = r'cache-size\s*=\s*10000' DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' - Docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') - Slow(lambda: re.search(CONFIG_LINE, Docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') + slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) # DNS Environment Variable behavior in combinations of modified pihole LTE settings @@ -91,14 +91,14 @@ def test_dnssec_enabled_with_CUSTOM_CACHE_SIZE(Docker, Slow, test_args): ('-e DNS1="1.2.3.4" -e DNS2="no"', 'custom DNS', '1.2.3.4', None ), ('-e DNS2="no"', 'custom DNS', '8.8.8.8', None ), ]) -def test_override_default_servers_with_DNS_EnvVars(Docker, Slow, args_env, expected_stdout, dns1, dns2): +def test_override_default_servers_with_dns_envvars(docker, slow, args_env, expected_stdout, dns1, dns2): ''' on first boot when DNS vars are NOT set explain default google DNS settings are used or when DNS vars are set override the pihole DNS settings ''' - assert Docker.run('test -f /.piholeFirstBoot').rc == 0 - function = Docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + assert docker.run('test -f /.piholeFirstBoot').rc == 0 + function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') assert expected_stdout in function.stdout expected_servers = 'server={}\n'.format(dns1) if dns2 == None else 'server={}\nserver={}\n'.format(dns1, dns2) - Slow(lambda: expected_servers == Docker.run('grep "^server=[^/]" /etc/dnsmasq.d/01-pihole.conf').stdout) + slow(lambda: expected_servers == docker.run('grep "^server=[^/]" /etc/dnsmasq.d/01-pihole.conf').stdout) #@pytest.mark.skipif(os.environ.get('CI') == 'true', @@ -115,31 +115,31 @@ def test_override_default_servers_with_DNS_EnvVars(Docker, Slow, args_env, expec ('-e DNS1="1.2.3.4" -e DNS2="2.2.3.4"', '1.2.3.4', '2.2.3.4', 'Docker DNS variables not used\nExisting DNS servers used (1.2.3.4 & 2.2.3.4'), ]) -def test_DNS_Envs_are_secondary_to_setupvars(Docker, Slow, args_env, expected_stdout, dns1, dns2): +def test_dns_envs_are_secondary_to_setupvars(docker, slow, args_env, expected_stdout, dns1, dns2): ''' on second boot when DNS vars are set just use pihole DNS settings or when DNS vars and FORCE_DNS var are set override the pihole DNS settings ''' # Given we are not booting for the first time - assert Docker.run('rm /.piholeFirstBoot').rc == 0 + assert docker.run('rm /.piholeFirstBoot').rc == 0 # and a user already has custom pihole dns variables in setup vars dns_count = 1 - setupVars = '/etc/pihole/setupVars.conf' - Docker.run('sed -i "/^PIHOLE_DNS/ d" {}'.format(setupVars)) - Docker.run('echo "PIHOLE_DNS_1={}" | tee -a {}'.format(dns1, setupVars)) + setupvars = '/etc/pihole/setupVars.conf' + docker.run('sed -i "/^PIHOLE_DNS/ d" {}'.format(setupvars)) + docker.run('echo "PIHOLE_DNS_1={}" | tee -a {}'.format(dns1, setupvars)) if dns2: - Docker.run('echo "PIHOLE_DNS_2={}" | tee -a {}'.format(dns2, setupVars)) - Docker.run('sync {}'.format(setupVars)) - Slow(lambda: 'PIHOLE_DNS' in Docker.run('cat {}'.format(setupVars)).stdout) + docker.run('echo "PIHOLE_DNS_2={}" | tee -a {}'.format(dns2, setupvars)) + docker.run('sync {}'.format(setupvars)) + slow(lambda: 'PIHOLE_DNS' in docker.run('cat {}'.format(setupvars)).stdout) # When we run setup dnsmasq during startup of the container - function = Docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') assert expected_stdout in function.stdout # Then the servers are still what the user had customized if forced dnsmasq is not set expected_servers = ['server={}'.format(dns1)] if dns2: expected_servers.append('server={}'.format(dns2)) - Slow(lambda: Docker.run('grep "^server=[^/]" /etc/dnsmasq.d/01-pihole.conf').stdout.strip().split('\n') == \ + slow(lambda: docker.run('grep "^server=[^/]" /etc/dnsmasq.d/01-pihole.conf').stdout.strip().split('\n') == \ expected_servers) @@ -147,11 +147,11 @@ def test_DNS_Envs_are_secondary_to_setupvars(Docker, Slow, args_env, expected_st ('', 'binding to default interface: eth0', 'PIHOLE_INTERFACE=eth0'), ('-e INTERFACE="br0"', 'binding to custom interface: br0', 'PIHOLE_INTERFACE=br0'), ]) -def test_DNS_interface_override_defaults(Docker, Slow, args_env, expected_stdout, expected_config_line): +def test_dns_interface_override_defaults(docker, slow, args_env, expected_stdout, expected_config_line): ''' When INTERFACE environment var is passed in, overwrite dnsmasq interface ''' - function = Docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') assert expected_stdout in function.stdout - Slow(lambda: expected_config_line + '\n' == Docker.run('grep "^PIHOLE_INTERFACE" /etc/pihole/setupVars.conf').stdout) + slow(lambda: expected_config_line + '\n' == docker.run('grep "^PIHOLE_INTERFACE" /etc/pihole/setupVars.conf').stdout) expected_debian_lines = [ @@ -165,14 +165,14 @@ expected_debian_lines = [ (expected_debian_lines, 1), (expected_debian_lines, 2) ]) -def test_debian_setup_php_env(Docker, expected_lines, repeat_function): +def test_debian_setup_php_env(docker, expected_lines, repeat_function): ''' confirm all expected output is there and nothing else ''' stdout = '' for _ in range(repeat_function): - stdout = Docker.run('. /bash_functions.sh ; eval `grep setup_php_env /start.sh`').stdout + stdout = docker.run('. /bash_functions.sh ; eval `grep setup_php_env /start.sh`').stdout for expected_line in expected_lines: search_config_cmd = "grep -c '{}' /etc/lighttpd/conf-enabled/15-fastcgi-php.conf".format(expected_line) - search_config_count = Docker.run(search_config_cmd) + search_config_count = docker.run(search_config_cmd) found_lines = int(search_config_count.stdout.rstrip('\n')) if found_lines > 1: assert False, f'Found line {expected_line} times (more than once): {found_lines}' @@ -181,43 +181,43 @@ def test_debian_setup_php_env(Docker, expected_lines, repeat_function): WEBPASSWORD_TEST_FUNCTION_COMMAND='. /bash_functions.sh ; eval `grep setup_web_password /start.sh`' -def test_webPassword_random_generation(Docker): +def test_webpassword_random_generation(docker): ''' When a user sets webPassword env the admin password gets set to that ''' - function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert 'assigning random password' in function.stdout.lower() @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) -@pytest.mark.parametrize('args_env,secure,setupVarsHash', [ +@pytest.mark.parametrize('args_env,secure,setupvars_hash', [ ('-e ServerIP=1.2.3.4 -e WEBPASSWORD=login', True, 'WEBPASSWORD=6060d59351e8c2f48140f01b2c3f3b61652f396c53a5300ae239ebfbe7d5ff08'), ('-e ServerIP=1.2.3.4 -e WEBPASSWORD=""', False, ''), ]) -def test_webPassword_env_assigns_password_to_file_or_removes_if_empty(Docker, args_env, secure, setupVarsHash): +def test_webpassword_env_assigns_password_to_file_or_removes_if_empty(docker, args_env, secure, setupvars_hash): ''' When a user sets webPassword env the admin password gets set or removed if empty ''' - function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) if secure: assert 'new password set' in function.stdout.lower() - assert Docker.run('grep -q \'{}\' {}'.format(setupVarsHash, '/etc/pihole/setupVars.conf')).rc == 0 + assert docker.run('grep -q \'{}\' {}'.format(setupvars_hash, '/etc/pihole/setupVars.conf')).rc == 0 else: assert 'password removed' in function.stdout.lower() - assert Docker.run('grep -q \'^WEBPASSWORD=$\' /etc/pihole/setupVars.conf').rc == 0 + assert docker.run('grep -q \'{}\' {}'.format('^WEBPASSWORD=$', '/etc/pihole/setupVars.conf')).rc == 0 @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize('test_args', ['-e WEBPASSWORD=login', '-e WEBPASSWORD=""']) -def test_env_always_updates_password(Docker, args_env, test_args): +def test_env_always_updates_password(docker, args_env, test_args): '''When a user sets the WEBPASSWORD environment variable, ensure it always sets the password''' - function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert '::: Assigning password defined by Environment Variable' in function.stdout @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) -def test_setupvars_trumps_random_password_if_set(Docker, args_env, test_args): - '''If a password is already set in setupVars, and no password is set in the environment variable, do not generate a random password''' - Docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair /etc/pihole/setupVars.conf WEBPASSWORD volumepass') - function = Docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) +def test_setupvars_trumps_random_password_if_set(docker, args_env, test_args): + '''If a password is already set in setupvars, and no password is set in the environment variable, do not generate a random password''' + docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair /etc/pihole/setupVars.conf WEBPASSWORD volumepass') + function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) assert 'Pre existing WEBPASSWORD found' in function.stdout - assert Docker.run('grep -q \'{}\' {}'.format('WEBPASSWORD=volumepass', '/etc/pihole/setupVars.conf')).rc == 0 + assert docker.run('grep -q \'{}\' {}'.format('WEBPASSWORD=volumepass', '/etc/pihole/setupVars.conf')).rc == 0 diff --git a/test/test_pihole_scripts.py b/test/test_pihole_scripts.py index b7fee89..572e554 100644 --- a/test/test_pihole_scripts.py +++ b/test/test_pihole_scripts.py @@ -8,47 +8,47 @@ def start_cmd(): @pytest.fixture -def RunningPiHole(DockerPersist, Slow, persist_webserver, persist_tag, start_cmd): - ''' Override the RunningPiHole to run and check for success of a +def running_pihole(docker_persist, slow, persist_webserver, persist_tag, start_cmd): + ''' Override the running_pihole to run and check for success of a pihole-FTL start based `pihole` script command Individual tests all must override start_cmd''' - #print DockerPersist.run('ps -ef').stdout - assert DockerPersist.dig.run('ping -c 1 test_pihole').rc == 0 - Slow(lambda: DockerPersist.run('pgrep pihole-FTL').rc == 0) - Slow(lambda: DockerPersist.run('pgrep {}'.format(persist_webserver)).rc == 0) - oldpid = DockerPersist.run('pidof pihole-FTL') - cmd = DockerPersist.run('pihole {}'.format(start_cmd)) - Slow(lambda: DockerPersist.run('pgrep pihole-FTL').rc == 0) - newpid = DockerPersist.run('pidof pihole-FTL') + #print docker_persist.run('ps -ef').stdout + assert docker_persist.dig.run('ping -c 1 test_pihole').rc == 0 + slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) + slow(lambda: docker_persist.run('pgrep {}'.format(persist_webserver)).rc == 0) + oldpid = docker_persist.run('pidof pihole-FTL') + cmd = docker_persist.run('pihole {}'.format(start_cmd)) + slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) + newpid = docker_persist.run('pidof pihole-FTL') for pid in [oldpid, newpid]: assert pid != '' # ensure a new pid for pihole-FTL appeared due to service restart assert oldpid != newpid assert cmd.rc == 0 # Save out cmd result to check different stdout of start/enable/disable - DockerPersist.cmd = cmd - return DockerPersist + docker_persist.cmd = cmd + return docker_persist @pytest.mark.parametrize('start_cmd,hostname,expected_ip, expected_messages', [ ('enable', 'pi.hole', '127.0.0.1', ['Blocking already enabled,','nothing to do']), ('disable', 'pi.hole', '127.0.0.1', ['Disabling blocking','Pi-hole Disabled']), ]) -def test_pihole_enable_disable_command(RunningPiHole, Dig, persist_tag, start_cmd, hostname, expected_ip, expected_messages): - ''' the start_cmd tests are all built into the RunningPiHole fixture in this file ''' +def test_pihole_enable_disable_command(running_pihole, dig, persist_tag, start_cmd, hostname, expected_ip, expected_messages): + ''' the start_cmd tests are all built into the running_pihole fixture in this file ''' dig_cmd = "dig +time=1 +noall +answer {} @test_pihole".format(hostname) - lookup = RunningPiHole.dig.run(dig_cmd) + lookup = running_pihole.dig.run(dig_cmd) assert lookup.rc == 0 lookup_ip = lookup.stdout.split()[4] assert lookup_ip == expected_ip for part_of_output in expected_messages: - assert part_of_output in RunningPiHole.cmd.stdout + assert part_of_output in running_pihole.cmd.stdout @pytest.mark.parametrize('start_cmd,expected_message', [ ('-up', 'Function not supported in Docker images') ]) -def test_pihole_update_command(RunningPiHole, start_cmd, expected_message): - assert RunningPiHole.cmd.stdout.strip() == expected_message +def test_pihole_update_command(running_pihole, start_cmd, expected_message): + assert running_pihole.cmd.stdout.strip() == expected_message diff --git a/test/test_start.py b/test/test_start.py index 2f44e08..2f5c7a4 100644 --- a/test/test_start.py +++ b/test/test_start.py @@ -7,9 +7,9 @@ import time # If the test runs /start.sh, do not let s6 run it too! Kill entrypoint to avoid race condition/duplicated execution @pytest.mark.parametrize('persist_entrypoint,persist_cmd,persist_args_env', [('--entrypoint=tail','-f /dev/null','')]) -def test_ServerIP_missing_is_not_required_anymore(RunningPiHole): +def test_serverip_missing_is_not_required_anymore(running_pihole): ''' When args to docker are empty start.sh exits saying ServerIP is required ''' - start = Docker.run('/start.sh') + start = docker.run('/start.sh') error_msg = "ERROR: To function correctly you must pass an environment variables of 'ServerIP' into the docker container" assert start.rc == 1 assert error_msg in start.stdout @@ -21,9 +21,9 @@ def test_ServerIP_missing_is_not_required_anymore(RunningPiHole): ('-e ServerIP="1.2.3.4" -e ServerIPv6="1234:1234:1234:ZZZZ"', "Environment variable (1234:1234:1234:ZZZZ) doesn't appear to be a valid IPv6 address",1), ('-e ServerIP="1.2.3.4" -e ServerIPv6="kernel"', "ERROR: You passed in IPv6 with a value of 'kernel'",1), ]) -def test_ServerIP_invalid_IPs_triggers_exit_error(Docker, error_msg, expect_rc): +def test_serverip_invalid_ips_triggers_exit_error(docker, error_msg, expect_rc): ''' When args to docker are empty start.sh exits saying ServerIP is required ''' - start = Docker.run('/start.sh') + start = docker.run('/start.sh') assert start.rc == expect_rc assert 'ERROR' in start.stdout assert error_msg in start.stdout @@ -33,15 +33,15 @@ def test_ServerIP_invalid_IPs_triggers_exit_error(Docker, error_msg, expect_rc): ('google-public-dns-a.google.com', '8.8.8.8'), ('b.resolvers.Level3.net', '4.2.2.2') ]) -def test_dns_responses(RunningPiHole, hostname, expected_ip): +def test_dns_responses(running_pihole, hostname, expected_ip): dig_cmd = "dig +time=1 +noall +answer {} @test_pihole | awk '{{ print $5 }}'".format(hostname) - lookup = RunningPiHole.dig.run(dig_cmd).stdout.rstrip('\n') + lookup = running_pihole.dig.run(dig_cmd).stdout.rstrip('\n') assert lookup == expected_ip -def test_indecies_are_present(RunningPiHole): - File = RunningPiHole.get_module('File') - File('/var/www/html/pihole/index.html').exists - File('/var/www/html/pihole/index.js').exists +def test_indecies_are_present(running_pihole): + file = running_pihole.get_module('File') + file('/var/www/html/pihole/index.html').exists + file('/var/www/html/pihole/index.js').exists def validate_curl(http_rc, expected_http_code, page_contents): if int(http_rc.rc) != 0 or int(http_rc.stdout) != expected_http_code: @@ -53,10 +53,10 @@ def validate_curl(http_rc, expected_http_code, page_contents): @pytest.mark.parametrize('addr', [ 'localhost' ] ) @pytest.mark.parametrize('url', [ '/admin/', '/admin/index.php' ] ) -def test_admin_requests_load_as_expected(RunningPiHole, version, addr, url): +def test_admin_requests_load_as_expected(running_pihole, version, addr, url): command = 'curl -L -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(addr, url) - http_rc = RunningPiHole.run(command) - page_contents = RunningPiHole.run('cat /tmp/curled_file ').stdout + http_rc = running_pihole.run(command) + page_contents = running_pihole.run('cat /tmp/curled_file ').stdout expected_http_code = 200 validate_curl(http_rc, expected_http_code, page_contents) From 29f81fcfbcdaa7d30c51f94f601c24f0cb4bc730 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 6 Jun 2022 21:58:09 +0100 Subject: [PATCH 06/18] Address Sonar rule S1192 (https://rules.sonarsource.com/python/RSPEC-1192) Signed-off-by: Adam Warner --- test/conftest.py | 10 +++--- test/test_bash_functions.py | 61 +++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index ac7174b..0c190f8 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -8,6 +8,7 @@ local_host = testinfra.get_host('local://') check_output = local_host.check_output DEBIAN_VERSION = os.environ.get('DEBIAN_VERSION', 'bullseye') +TAIL_DEV_NULL='tail -f /dev/null' @pytest.fixture() def run_and_stream_command_output(): @@ -52,7 +53,7 @@ def docker_generic(request, _test_args, _args, _image, _cmd, _entrypoint): docker_run = 'docker run -d -t {args} {test_args} {entry} {image} {cmd}'\ .format(args=_args, test_args=_test_args, entry=_entrypoint, image=_image, cmd=_cmd) # Print a human runable version of the container run command for faster debugging - print(docker_run.replace('-d -t', '--rm -it').replace('tail -f /dev/null', 'bash')) + print(docker_run.replace('-d -t', '--rm -it').replace(TAIL_DEV_NULL, 'bash')) docker_id = check_output(docker_run) def teardown(): @@ -112,7 +113,7 @@ def image(tag): @pytest.fixture() def cmd(): - return 'tail -f /dev/null' + return TAIL_DEV_NULL @pytest.fixture(scope='module') def persist_arch(): @@ -164,7 +165,7 @@ def persist_image(persist_tag): @pytest.fixture(scope='module') def persist_cmd(): - return 'tail -f /dev/null' + return TAIL_DEV_NULL @pytest.fixture(scope='module') def persist_entrypoint(): @@ -197,7 +198,7 @@ def dig(): def _dig(docker_id): args = '--link {}:test_pihole'.format(docker_id) image = 'azukiapp/dig' - cmd = 'tail -f /dev/null' + cmd = TAIL_DEV_NULL dig_container = docker_generic(request, '', args, image, cmd, '') return dig_container return _dig @@ -211,3 +212,4 @@ def running_pihole(docker_persist, slow, persist_webserver): slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) slow(lambda: docker_persist.run('pgrep lighttpd').rc == 0) return docker_persist + diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index 451fcb7..f24dddc 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -3,6 +3,16 @@ import os import pytest import re +SETUPVARS_LOC='/etc/pihole/setupVars.conf' +DNSMASQ_CONFIG_LOC = '/etc/dnsmasq.d/01-pihole.conf' +EVAL_SETUP_DNSMASQ='. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`' +EVAL_SETUP_WEB_PASSWORD='. /bash_functions.sh ; eval `grep setup_web_password /start.sh`' + +def _cat(file): + return 'cat {}'.format(file) + +def _grep(string, file): + return 'grep -q \'{}\' {}'.format(string,file) @pytest.mark.parametrize('test_args,expected_ipv6,expected_stdout', [ ('', True, 'IPv4 and IPv6'), @@ -35,7 +45,7 @@ def test_overrides_default_web_port(docker, slow, test_args): function = docker.run('. /bash_functions.sh ; eval `grep setup_web_port /start.sh`') assert "Custom WEB_PORT set to 999" in function.stdout assert "INFO: Without proper router DNAT forwarding to 127.0.0.1:999, you may not get any blocked websites on ads" in function.stdout - slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(WEB_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(WEB_CONFIG)).stdout) != None) @pytest.mark.parametrize('test_args,expected_error', [ @@ -52,11 +62,10 @@ def test_bad_input_to_web_port(docker, test_args, expected_error): def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size): ''' Changes the cache_size setting to increase or decrease the cache size for dnsmasq''' CONFIG_LINE = r'cache-size\s*=\s*{}'.format(cache_size) - DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' function = docker.run('echo ${CUSTOM_CACHE_SIZE};. ./bash_functions.sh; echo ${CUSTOM_CACHE_SIZE}; eval `grep setup_dnsmasq /start.sh`') assert "Custom CUSTOM_CACHE_SIZE set to {}".format(cache_size) in function.stdout - slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) @pytest.mark.parametrize('test_args', [ @@ -65,20 +74,18 @@ def test_overrides_default_custom_cache_size(docker, slow, test_args, cache_size ]) def test_bad_input_to_custom_cache_size(docker, slow, test_args): CONFIG_LINE = r'cache-size\s*=\s*10000' - DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') - slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) @pytest.mark.parametrize('test_args', [ '-e DNSSEC="true" -e CUSTOM_CACHE_SIZE="0"', ]) def test_dnssec_enabled_with_custom_cache_size(docker, slow, test_args): CONFIG_LINE = r'cache-size\s*=\s*10000' - DNSMASQ_CONFIG = '/etc/dnsmasq.d/01-pihole.conf' docker.run('. ./bash_functions.sh; eval `grep setup_dnsmasq /start.sh`') - slow(lambda: re.search(CONFIG_LINE, docker.run('cat {}'.format(DNSMASQ_CONFIG)).stdout) != None) + slow(lambda: re.search(CONFIG_LINE, docker.run(_cat(DNSMASQ_CONFIG_LOC)).stdout) != None) # DNS Environment Variable behavior in combinations of modified pihole LTE settings @@ -95,7 +102,7 @@ def test_override_default_servers_with_dns_envvars(docker, slow, args_env, expec ''' on first boot when DNS vars are NOT set explain default google DNS settings are used or when DNS vars are set override the pihole DNS settings ''' assert docker.run('test -f /.piholeFirstBoot').rc == 0 - function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + function = docker.run(EVAL_SETUP_DNSMASQ) assert expected_stdout in function.stdout expected_servers = 'server={}\n'.format(dns1) if dns2 == None else 'server={}\nserver={}\n'.format(dns1, dns2) slow(lambda: expected_servers == docker.run('grep "^server=[^/]" /etc/dnsmasq.d/01-pihole.conf').stdout) @@ -121,18 +128,16 @@ def test_dns_envs_are_secondary_to_setupvars(docker, slow, args_env, expected_st # Given we are not booting for the first time assert docker.run('rm /.piholeFirstBoot').rc == 0 - # and a user already has custom pihole dns variables in setup vars - dns_count = 1 - setupvars = '/etc/pihole/setupVars.conf' - docker.run('sed -i "/^PIHOLE_DNS/ d" {}'.format(setupvars)) - docker.run('echo "PIHOLE_DNS_1={}" | tee -a {}'.format(dns1, setupvars)) + # and a user already has custom pihole dns variables in setup vars + docker.run('sed -i "/^PIHOLE_DNS/ d" {}'.format(SETUPVARS_LOC)) + docker.run('echo "PIHOLE_DNS_1={}" | tee -a {}'.format(dns1, SETUPVARS_LOC)) if dns2: - docker.run('echo "PIHOLE_DNS_2={}" | tee -a {}'.format(dns2, setupvars)) - docker.run('sync {}'.format(setupvars)) - slow(lambda: 'PIHOLE_DNS' in docker.run('cat {}'.format(setupvars)).stdout) + docker.run('echo "PIHOLE_DNS_2={}" | tee -a {}'.format(dns2, SETUPVARS_LOC)) + docker.run('sync {}'.format(SETUPVARS_LOC)) + slow(lambda: 'PIHOLE_DNS' in docker.run(_cat(SETUPVARS_LOC)).stdout) # When we run setup dnsmasq during startup of the container - function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + function = docker.run(EVAL_SETUP_DNSMASQ) assert expected_stdout in function.stdout # Then the servers are still what the user had customized if forced dnsmasq is not set @@ -149,9 +154,9 @@ def test_dns_envs_are_secondary_to_setupvars(docker, slow, args_env, expected_st ]) def test_dns_interface_override_defaults(docker, slow, args_env, expected_stdout, expected_config_line): ''' When INTERFACE environment var is passed in, overwrite dnsmasq interface ''' - function = docker.run('. /bash_functions.sh ; eval `grep "^setup_dnsmasq " /start.sh`') + function = docker.run(EVAL_SETUP_DNSMASQ) assert expected_stdout in function.stdout - slow(lambda: expected_config_line + '\n' == docker.run('grep "^PIHOLE_INTERFACE" /etc/pihole/setupVars.conf').stdout) + slow(lambda: expected_config_line + '\n' == docker.run('grep "^PIHOLE_INTERFACE" {}'.format(SETUPVARS_LOC)).stdout) expected_debian_lines = [ @@ -178,12 +183,10 @@ def test_debian_setup_php_env(docker, expected_lines, repeat_function): assert False, f'Found line {expected_line} times (more than once): {found_lines}' -WEBPASSWORD_TEST_FUNCTION_COMMAND='. /bash_functions.sh ; eval `grep setup_web_password /start.sh`' - def test_webpassword_random_generation(docker): ''' When a user sets webPassword env the admin password gets set to that ''' - function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(EVAL_SETUP_WEB_PASSWORD) assert 'assigning random password' in function.stdout.lower() @@ -194,21 +197,21 @@ def test_webpassword_random_generation(docker): ]) def test_webpassword_env_assigns_password_to_file_or_removes_if_empty(docker, args_env, secure, setupvars_hash): ''' When a user sets webPassword env the admin password gets set or removed if empty ''' - function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(EVAL_SETUP_WEB_PASSWORD) if secure: assert 'new password set' in function.stdout.lower() - assert docker.run('grep -q \'{}\' {}'.format(setupvars_hash, '/etc/pihole/setupVars.conf')).rc == 0 + assert docker.run(_grep(setupvars_hash, SETUPVARS_LOC)).rc == 0 else: assert 'password removed' in function.stdout.lower() - assert docker.run('grep -q \'{}\' {}'.format('^WEBPASSWORD=$', '/etc/pihole/setupVars.conf')).rc == 0 + assert docker.run(_grep('^WEBPASSWORD=$', SETUPVARS_LOC)).rc == 0 @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) @pytest.mark.parametrize('test_args', ['-e WEBPASSWORD=login', '-e WEBPASSWORD=""']) def test_env_always_updates_password(docker, args_env, test_args): '''When a user sets the WEBPASSWORD environment variable, ensure it always sets the password''' - function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + function = docker.run(EVAL_SETUP_WEB_PASSWORD) assert '::: Assigning password defined by Environment Variable' in function.stdout @@ -216,8 +219,8 @@ def test_env_always_updates_password(docker, args_env, test_args): @pytest.mark.parametrize('entrypoint,cmd', [('--entrypoint=tail','-f /dev/null')]) def test_setupvars_trumps_random_password_if_set(docker, args_env, test_args): '''If a password is already set in setupvars, and no password is set in the environment variable, do not generate a random password''' - docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair /etc/pihole/setupVars.conf WEBPASSWORD volumepass') - function = docker.run(WEBPASSWORD_TEST_FUNCTION_COMMAND) + docker.run('. /opt/pihole/utils.sh ; addOrEditKeyValPair {} WEBPASSWORD volumepass'.format(SETUPVARS_LOC)) + function = docker.run(EVAL_SETUP_WEB_PASSWORD) assert 'Pre existing WEBPASSWORD found' in function.stdout - assert docker.run('grep -q \'{}\' {}'.format('WEBPASSWORD=volumepass', '/etc/pihole/setupVars.conf')).rc == 0 + assert docker.run(_grep('WEBPASSWORD=volumepass', SETUPVARS_LOC)).rc == 0 From cb16942096d6bf634c9eaeca6ef8a8cf9ee91f6a Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 6 Jun 2022 22:04:44 +0100 Subject: [PATCH 07/18] Address Sonar rules S125 (https://rules.sonarsource.com/python/RSPEC-125) and S1481 (https://rules.sonarsource.com/python/RSPEC-1481) Signed-off-by: Adam Warner --- test/test_bash_functions.py | 3 +-- test/test_pihole_scripts.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index f24dddc..6898072 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -172,9 +172,8 @@ expected_debian_lines = [ ]) def test_debian_setup_php_env(docker, expected_lines, repeat_function): ''' confirm all expected output is there and nothing else ''' - stdout = '' for _ in range(repeat_function): - stdout = docker.run('. /bash_functions.sh ; eval `grep setup_php_env /start.sh`').stdout + docker.run('. /bash_functions.sh ; eval `grep setup_php_env /start.sh`').stdout for expected_line in expected_lines: search_config_cmd = "grep -c '{}' /etc/lighttpd/conf-enabled/15-fastcgi-php.conf".format(expected_line) search_config_count = docker.run(search_config_cmd) diff --git a/test/test_pihole_scripts.py b/test/test_pihole_scripts.py index 572e554..7c0ae8f 100644 --- a/test/test_pihole_scripts.py +++ b/test/test_pihole_scripts.py @@ -13,7 +13,6 @@ def running_pihole(docker_persist, slow, persist_webserver, persist_tag, start_c pihole-FTL start based `pihole` script command Individual tests all must override start_cmd''' - #print docker_persist.run('ps -ef').stdout assert docker_persist.dig.run('ping -c 1 test_pihole').rc == 0 slow(lambda: docker_persist.run('pgrep pihole-FTL').rc == 0) slow(lambda: docker_persist.run('pgrep {}'.format(persist_webserver)).rc == 0) From 60e252c414807647767ffd3ac3c45d96b99da19f Mon Sep 17 00:00:00 2001 From: mmvanheusden <50550545+mmvanheusden@users.noreply.github.com> Date: Tue, 7 Jun 2022 16:06:15 +0200 Subject: [PATCH 08/18] Remove random tab in the readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fd6b241..e3e5aca 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ services: # Volumes store your data between container upgrades volumes: - './etc-pihole:/etc/pihole' - - './etc-dnsmasq.d:/etc/dnsmasq.d' + - './etc-dnsmasq.d:/etc/dnsmasq.d' # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities cap_add: - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed From b7016668b4d840806df4e90d1b277f6081ac5079 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 12 Jun 2022 12:59:18 +0100 Subject: [PATCH 09/18] Account for log files being moved to /var/log/pihole/ Signed-off-by: Adam Warner --- s6/debian-root/etc/services.d/pihole-FTL/run | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/s6/debian-root/etc/services.d/pihole-FTL/run b/s6/debian-root/etc/services.d/pihole-FTL/run index 00a75a0..bc688a0 100644 --- a/s6/debian-root/etc/services.d/pihole-FTL/run +++ b/s6/debian-root/etc/services.d/pihole-FTL/run @@ -9,13 +9,13 @@ rm /run/pihole/FTL.sock 2> /dev/null mkdir -pm 0755 /run/pihole [[ ! -f /run/pihole-FTL.pid ]] && install /dev/null /run/pihole-FTL.pid [[ ! -f /run/pihole-FTL.port ]] && install /dev/null /run/pihole-FTL.port -[[ ! -f /var/log/pihole-FTL.log ]] && install /dev/null /var/log/pihole-FTL.log -[[ ! -f /var/log/pihole.log ]] && install /dev/null /var/log/pihole.log +[[ ! -f /var/log/pihole/pihole-FTL.log ]] && install /dev/null /var/log/pihole/pihole-FTL.log +[[ ! -f /var/log/pihole/pihole.log ]] && install /dev/null /var/log/pihole/pihole.log [[ ! -f /etc/pihole/dhcp.leases ]] && install /dev/null /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit all necessary files -chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole-FTL.log /var/log/pihole.log /etc/pihole/dhcp.leases /run/pihole /etc/pihole -chmod 0644 /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole-FTL.log /var/log/pihole.log /etc/pihole/dhcp.leases +chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/pihole-FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases /run/pihole /etc/pihole +chmod 0644 /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/pihole-FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist chmod -f 0644 /etc/pihole/macvendor.db @@ -24,6 +24,18 @@ chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pih # Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist chmod -f 0664 /etc/pihole/pihole-FTL.db +# Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole/ +# Should be removed with Pi-hole v6.0 +if [ ! -f /var/log/pihole.log ]; then + ln -s /var/log/pihole/pihole.log /var/log/pihole.log + chown -h pihole:pihole /var/log/pihole.log + +fi +if [ ! -f /var/log/pihole-FTL.log ]; then + ln -s /var/log/pihole/pihole-FTL.log /var/log/pihole-FTL.log + chown -h pihole:pihole /var/log/pihole-FTL.log +fi + # Call capsh with the detected capabilities capsh --inh=${CAP_STR:1} --addamb=${CAP_STR:1} --user=$DNSMASQ_USER --keep=1 -- -c "/usr/bin/pihole-FTL $FTL_CMD >/dev/null 2>&1" From 1900d567c941803ef23247105b0e761c86df6db6 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 12 Jun 2022 13:10:12 +0100 Subject: [PATCH 10/18] Mop up some other references Signed-off-by: Adam Warner --- docker-compose-nginx-proxy.yml | 2 +- s6/debian-root/etc/cont-init.d/20-start.sh | 2 +- s6/debian-root/etc/services.d/pihole-FTL/run | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose-nginx-proxy.yml b/docker-compose-nginx-proxy.yml index fe74aea..48b34f9 100644 --- a/docker-compose-nginx-proxy.yml +++ b/docker-compose-nginx-proxy.yml @@ -24,7 +24,7 @@ services: - './etc-pihole:/etc/pihole' - './etc-dnsmasq.d:/etc/dnsmasq.d' # run `touch ./var-log/pihole.log` first unless you like errors - # - './var-log/pihole.log:/var/log/pihole.log' + # - './var-log/pihole.log:/var/log/pihole/pihole.log' # Recommended but not required (DHCP needs NET_ADMIN) # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities cap_add: diff --git a/s6/debian-root/etc/cont-init.d/20-start.sh b/s6/debian-root/etc/cont-init.d/20-start.sh index 97cd6ab..78efae6 100644 --- a/s6/debian-root/etc/cont-init.d/20-start.sh +++ b/s6/debian-root/etc/cont-init.d/20-start.sh @@ -28,7 +28,7 @@ if [ -z "$SKIPGRAVITYONBOOT" ] || [ ! -e "${gravityDBfile}" ]; then echo " Ignoring SKIPGRAVITYONBOOT on this occaision." fi - echo '@reboot root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole_updateGravity.log || cat /var/log/pihole_updateGravity.log' > /etc/cron.d/gravity-on-boot + echo '@reboot root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole/pihole_updateGravity.log || cat /var/log/pihole/pihole_updateGravity.log' > /etc/cron.d/gravity-on-boot else echo " Skipping Gravity Database Update." [ ! -e /etc/cron.d/gravity-on-boot ] || rm /etc/cron.d/gravity-on-boot &>/dev/null diff --git a/s6/debian-root/etc/services.d/pihole-FTL/run b/s6/debian-root/etc/services.d/pihole-FTL/run index bc688a0..11b6f98 100644 --- a/s6/debian-root/etc/services.d/pihole-FTL/run +++ b/s6/debian-root/etc/services.d/pihole-FTL/run @@ -41,5 +41,5 @@ capsh --inh=${CAP_STR:1} --addamb=${CAP_STR:1} --user=$DNSMASQ_USER --keep=1 -- # Notes on above: # - DNSMASQ_USER default of pihole is in Dockerfile & can be overwritten by runtime container env -# - /var/log/pihole*.log has FTL's output that no-daemon would normally print in FG too +# - /var/log/pihole/pihole*.log has FTL's output that no-daemon would normally print in FG too # prevent duplicating it in docker logs by sending to dev null From f17898bf6f402268a626e7e24c7dab14635cfdde Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 12 Jun 2022 13:37:39 +0100 Subject: [PATCH 11/18] Also account for /var/log/lighttpd file name changes Signed-off-by: Adam Warner --- Dockerfile | 2 +- .../etc/services.d/lighttpd-access-log/run | 2 +- s6/debian-root/etc/services.d/lighttpd-error-log/run | 2 +- s6/debian-root/etc/services.d/lighttpd/run | 12 ++++++------ test/test_bash_functions.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5cd5d9c..067f969 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN bash -ex install.sh 2>&1 && \ ARG PHP_ENV_CONFIG ENV PHP_ENV_CONFIG /etc/lighttpd/conf-enabled/15-fastcgi-php.conf ARG PHP_ERROR_LOG -ENV PHP_ERROR_LOG /var/log/lighttpd/error.log +ENV PHP_ERROR_LOG /var/log/lighttpd/error-pihole.log COPY ./start.sh / COPY ./bash_functions.sh / diff --git a/s6/debian-root/etc/services.d/lighttpd-access-log/run b/s6/debian-root/etc/services.d/lighttpd-access-log/run index 1473767..61d7cbb 100644 --- a/s6/debian-root/etc/services.d/lighttpd-access-log/run +++ b/s6/debian-root/etc/services.d/lighttpd-access-log/run @@ -2,4 +2,4 @@ s6-echo "Starting lighttpd-access-log" -s6-setuidgid www-data cat /var/log/lighttpd/access.log 2>&1 +s6-setuidgid www-data cat /var/log/lighttpd/access-pihole.log 2>&1 diff --git a/s6/debian-root/etc/services.d/lighttpd-error-log/run b/s6/debian-root/etc/services.d/lighttpd-error-log/run index c0636fc..45e666a 100644 --- a/s6/debian-root/etc/services.d/lighttpd-error-log/run +++ b/s6/debian-root/etc/services.d/lighttpd-error-log/run @@ -2,4 +2,4 @@ s6-echo "Starting lighttpd-error-log" -s6-setuidgid www-data cat /var/log/lighttpd/error.log 2>&1 +s6-setuidgid www-data cat /var/log/lighttpd/error-pihole.log 2>&1 diff --git a/s6/debian-root/etc/services.d/lighttpd/run b/s6/debian-root/etc/services.d/lighttpd/run index 2cd314a..98140b4 100644 --- a/s6/debian-root/etc/services.d/lighttpd/run +++ b/s6/debian-root/etc/services.d/lighttpd/run @@ -4,7 +4,7 @@ s6-echo "Starting lighttpd" if [[ 1 -eq ${WEBLOGS_STDOUT:-0} ]]; then #lighthttpd cannot use /dev/stdout https://redmine.lighttpd.net/issues/2731 - for fi in /var/log/lighttpd/access.log /var/log/lighttpd/error.log + for fi in /var/log/lighttpd/access-pihole.log /var/log/lighttpd/erro-pihole.log do if [[ ! -p ${fi} ]]; then rm -f ${fi} @@ -17,16 +17,16 @@ if [[ 1 -eq ${WEBLOGS_STDOUT:-0} ]]; then sleep 2 else #remove fifo if exists - [[ -p /var/log/lighttpd/access.log ]] && rm -Rf /var/log/lighttpd/access.log - [[ -p /var/log/lighttpd/error.log ]] && rm -Rf /var/log/lighttpd/error.log + [[ -p /var/log/lighttpd/access-pihole.log ]] && rm -Rf /var/log/lighttpd/access-pihole.log + [[ -p /var/log/lighttpd/error-pihole.log ]] && rm -Rf /var/log/lighttpd/error-pihole.log # install /dev/null log files to ensure they exist (create if non-existing, preserve if existing) - [[ ! -f /var/log/lighttpd/access.log ]] && install /dev/null /var/log/lighttpd/access.log - [[ ! -f /var/log/lighttpd/error.log ]] && install /dev/null /var/log/lighttpd/error.log + [[ ! -f /var/log/lighttpd/access-pihole.log ]] && install /dev/null /var/log/lighttpd/access-pihole.log + [[ ! -f /var/log/lighttpd/error-pihole.log ]] && install /dev/null /var/log/lighttpd/error-pihole.log # Ensure that permissions are set so that lighttpd can write to the logs chown -R www-data:www-data /var/log/lighttpd - chmod 0644 /var/log/lighttpd/access.log /var/log/lighttpd/error.log + chmod 0644 /var/log/lighttpd/access-pihole.log /var/log/lighttpd/error-pihole.log fi lighttpd -D -f /etc/lighttpd/lighttpd.conf diff --git a/test/test_bash_functions.py b/test/test_bash_functions.py index 6898072..ebdfce1 100644 --- a/test/test_bash_functions.py +++ b/test/test_bash_functions.py @@ -162,7 +162,7 @@ def test_dns_interface_override_defaults(docker, slow, args_env, expected_stdout expected_debian_lines = [ '"VIRTUAL_HOST" => "127.0.0.1"', '"ServerIP" => "127.0.0.1"', - '"PHP_ERROR_LOG" => "/var/log/lighttpd/error.log"' + '"PHP_ERROR_LOG" => "/var/log/lighttpd/error-pihole.log"' ] From 05bf32abdacc9eaf48de271f8d88cd0dc761e364 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 12 Jun 2022 17:56:47 +0100 Subject: [PATCH 12/18] Update s6/debian-root/etc/services.d/lighttpd/run Co-authored-by: yubiuser Signed-off-by: Adam Warner --- s6/debian-root/etc/services.d/lighttpd/run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s6/debian-root/etc/services.d/lighttpd/run b/s6/debian-root/etc/services.d/lighttpd/run index 98140b4..8a314fb 100644 --- a/s6/debian-root/etc/services.d/lighttpd/run +++ b/s6/debian-root/etc/services.d/lighttpd/run @@ -4,7 +4,7 @@ s6-echo "Starting lighttpd" if [[ 1 -eq ${WEBLOGS_STDOUT:-0} ]]; then #lighthttpd cannot use /dev/stdout https://redmine.lighttpd.net/issues/2731 - for fi in /var/log/lighttpd/access-pihole.log /var/log/lighttpd/erro-pihole.log + for fi in /var/log/lighttpd/access-pihole.log /var/log/lighttpd/error-pihole.log do if [[ ! -p ${fi} ]]; then rm -f ${fi} From a6d0e49ed1a206e62c557df72de4c92d87718ed7 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Thu, 30 Jun 2022 17:30:30 +0800 Subject: [PATCH 13/18] Update Python dependency - urllib3 from v1.25.8 to v1.25.9 https://www.cve.org/CVERecord?id=CVE-2020-26137 > urllib3 before 1.25.9 allows CRLF injection if the attacker controls > the HTTP request method, as demonstrated by inserting CR and LF > control characters in the first argument of putrequest(). NOTE: this > is similar to CVE-2020-26116. Signed-off-by: Peter Dave Hello --- Pipfile | 2 +- Pipfile.lock | 15 +++++++-------- requirements.txt | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Pipfile b/Pipfile index 091ce68..661be15 100644 --- a/Pipfile +++ b/Pipfile @@ -48,7 +48,7 @@ testinfra = "==3.3.0" texttable = "==1.6.2" toml = "==0.10.0" tox = "==3.14.3" -urllib3 = "==1.25.8" +urllib3 = "==1.25.9" virtualenv = "==16.7.9" wcwidth = "==0.1.7" zipp = "==0.6.0" diff --git a/Pipfile.lock b/Pipfile.lock index d8a7c49..18890f0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2c7f1fb7f001bf70bba7309859b06dc323040f21518b32ee8993aa823c27df15" + "sha256": "7b26c964f32db6ff56972abb88bd5bea6b4867dea49914f36999a2adc89eab1f" }, "pipfile-spec": 6, "requires": { @@ -381,11 +381,10 @@ }, "packaging": { "hashes": [ - "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", - "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==20.9" + "version": "==21.3" }, "pathlib2": { "hashes": [ @@ -577,11 +576,11 @@ }, "urllib3": { "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" ], "index": "pypi", - "version": "==1.25.8" + "version": "==1.25.9" }, "virtualenv": { "hashes": [ diff --git a/requirements.txt b/requirements.txt index 0d0a47a..a92ce3b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -47,7 +47,7 @@ testinfra==3.3.0 texttable==1.6.2 toml==0.10.0 tox==3.14.3 -urllib3==1.25.8 +urllib3==1.25.9 virtualenv==16.7.9 wcwidth==0.1.7 websocket-client==0.57.0 From aacc3efc930843f7356ce44ddf5d2425bdbdd975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 4 Jul 2022 16:03:16 +0200 Subject: [PATCH 14/18] Run stale workflow only once a day at 08:00 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 53335c8..74dbf0b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,7 @@ name: Mark stale issues on: schedule: - - cron: '0 * * * *' + - cron: '0 8 * * *' workflow_dispatch: jobs: From 855086caa783c851da71216636295868788ac36f Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 4 Jul 2022 15:40:53 +0100 Subject: [PATCH 15/18] Update s6/debian-root/etc/services.d/pihole-FTL/run Signed-off-by: Adam Warner --- s6/debian-root/etc/services.d/pihole-FTL/run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s6/debian-root/etc/services.d/pihole-FTL/run b/s6/debian-root/etc/services.d/pihole-FTL/run index 11b6f98..831145d 100644 --- a/s6/debian-root/etc/services.d/pihole-FTL/run +++ b/s6/debian-root/etc/services.d/pihole-FTL/run @@ -9,7 +9,7 @@ rm /run/pihole/FTL.sock 2> /dev/null mkdir -pm 0755 /run/pihole [[ ! -f /run/pihole-FTL.pid ]] && install /dev/null /run/pihole-FTL.pid [[ ! -f /run/pihole-FTL.port ]] && install /dev/null /run/pihole-FTL.port -[[ ! -f /var/log/pihole/pihole-FTL.log ]] && install /dev/null /var/log/pihole/pihole-FTL.log +[[ ! -f /var/log/pihole/FTL.log ]] && install /dev/null /var/log/pihole/FTL.log [[ ! -f /var/log/pihole/pihole.log ]] && install /dev/null /var/log/pihole/pihole.log [[ ! -f /etc/pihole/dhcp.leases ]] && install /dev/null /etc/pihole/dhcp.leases From 8fae8a1fdcd92ac7073290cf3293840a52264793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 5 Jul 2022 10:24:37 +0200 Subject: [PATCH 16/18] Fix close-issue-reason MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 74dbf0b..7b59a02 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -23,4 +23,4 @@ jobs: exempt-issue-labels: 'pinned, Fixed in next release, bug, never-stale, documentation, investigating' exempt-all-issue-assignees: true operations-per-run: 300 - stale-issue-reason: 'not_planned' + close-issue-reason: 'not_planned' From 8153363b2dea2f64ee2eb7010c842bdc107b927e Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 6 Jul 2022 01:27:07 +0800 Subject: [PATCH 17/18] Update Python dependency - urllib3 & requests - Update urllib3 from v1.25.9 to v1.26.5 - Update requests from v2.22.0 to v2.28.1 There's a medium severity CVE in urllib3, before v1.26.5, but we can't only just update urllib3 because there will be a dependency conflict. requests also needs to be updated. CVE reference: https://www.cve.org/CVERecord?id=CVE-2021-33503 > An issue was discovered in urllib3 before 1.26.5. When provided with a > URL containing many @ characters in the authority component, the > authority regular expression exhibits catastrophic backtracking, > causing a denial of service if a URL were passed as a parameter or > redirected to via an HTTP redirect. Signed-off-by: Peter Dave Hello --- Pipfile | 4 ++-- Pipfile.lock | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Pipfile b/Pipfile index 661be15..b1a81f6 100644 --- a/Pipfile +++ b/Pipfile @@ -40,7 +40,7 @@ pytest = "==4.6.8" pytest-cov = "==2.8.1" pytest-forked = "==1.1.3" pytest-xdist = "==1.31.0" -requests = "==2.22.0" +requests = "==2.28.1" scandir = "==1.10.0" six = "==1.13.0" subprocess32 = "==3.5.4" @@ -48,7 +48,7 @@ testinfra = "==3.3.0" texttable = "==1.6.2" toml = "==0.10.0" tox = "==3.14.3" -urllib3 = "==1.25.9" +urllib3 = "==1.26.5" virtualenv = "==16.7.9" wcwidth = "==0.1.7" zipp = "==0.6.0" diff --git a/Pipfile.lock b/Pipfile.lock index 18890f0..9016887 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7b26c964f32db6ff56972abb88bd5bea6b4867dea49914f36999a2adc89eab1f" + "sha256": "3acc0cd5a21768bc88eb864826f4309a3fe26d525f14dddd17d33a0c2490e57c" }, "pipfile-spec": 6, "requires": { @@ -143,6 +143,13 @@ "index": "pypi", "version": "==3.0.4" }, + "charset-normalizer": { + "hashes": [ + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + ], + "version": "==2.1.0" + }, "configparser": { "hashes": [ "sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c", @@ -501,11 +508,11 @@ }, "requests": { "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" ], "index": "pypi", - "version": "==2.22.0" + "version": "==2.28.1" }, "scandir": { "hashes": [ @@ -576,11 +583,11 @@ }, "urllib3": { "hashes": [ - "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", - "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" + "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c", + "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098" ], "index": "pypi", - "version": "==1.25.9" + "version": "==1.26.5" }, "virtualenv": { "hashes": [ From 33bae3207f84a962c79818027b5e3d45a2d631f8 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 8 Jul 2022 17:25:29 +0100 Subject: [PATCH 18/18] Also account for renaming of pihole-FTL.log -> FTL.log Signed-off-by: Adam Warner --- s6/debian-root/etc/services.d/pihole-FTL/run | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/s6/debian-root/etc/services.d/pihole-FTL/run b/s6/debian-root/etc/services.d/pihole-FTL/run index 831145d..ababe8d 100644 --- a/s6/debian-root/etc/services.d/pihole-FTL/run +++ b/s6/debian-root/etc/services.d/pihole-FTL/run @@ -6,7 +6,7 @@ rm -f /dev/shm/FTL-* 2> /dev/null rm /run/pihole/FTL.sock 2> /dev/null # install /dev/null files to ensure they exist (create if non-existing, preserve if existing) -mkdir -pm 0755 /run/pihole +mkdir -pm 0755 /run/pihole /var/log/pihole [[ ! -f /run/pihole-FTL.pid ]] && install /dev/null /run/pihole-FTL.pid [[ ! -f /run/pihole-FTL.port ]] && install /dev/null /run/pihole-FTL.port [[ ! -f /var/log/pihole/FTL.log ]] && install /dev/null /var/log/pihole/FTL.log @@ -14,8 +14,8 @@ mkdir -pm 0755 /run/pihole [[ ! -f /etc/pihole/dhcp.leases ]] && install /dev/null /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit all necessary files -chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/pihole-FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases /run/pihole /etc/pihole -chmod 0644 /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/pihole-FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases +chown pihole:pihole /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases /run/pihole /etc/pihole +chmod 0644 /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist chmod -f 0644 /etc/pihole/macvendor.db @@ -32,7 +32,7 @@ if [ ! -f /var/log/pihole.log ]; then fi if [ ! -f /var/log/pihole-FTL.log ]; then - ln -s /var/log/pihole/pihole-FTL.log /var/log/pihole-FTL.log + ln -s /var/log/pihole/FTL.log /var/log/pihole-FTL.log chown -h pihole:pihole /var/log/pihole-FTL.log fi