ufw-docker/test/ufw-docker.test.sh

861 lines
30 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
working_dir="$(cd "$(dirname "$BASH_SOURCE")"; pwd -P)"
source "$working_dir"/bach/bach.sh
@setup {
set -euo pipefail
}
@setup-test {
@mocktrue ufw status
@mocktrue grep -Fq "Status: active"
@mock iptables --version
@mocktrue grep -F '(legacy)'
@mocktrue docker -v
@mock docker -v === @stdout Docker version 0.0.0, build dummy
@mockpipe remove_blank_lines
#@ignore echo
@ignore err
builtin source <(@sed -n -e '/^# UFW-DOCKER GLOBAL VARIABLES START #$/,/^# UFW-DOCKER GLOBAL VARIABLES END #$/{' -e '/^PATH=/d' -e 'p' -e '}' "$working_dir/../ufw-docker")
UFW_DOCKER_AGENT_IMAGE=chaifeng/ufw-docker-agent:090502-legacy
}
function ufw-docker() {
@source <(@sed -n '/^# __main__$/,$p' "$working_dir/../ufw-docker") "$@"
}
function load-ufw-docker-function() {
set -euo pipefail
@load_function "$working_dir/../ufw-docker" "$1"
}
test-ufw-docker-init-legacy() {
@mocktrue grep -F '(legacy)'
@source <(@sed '/PATH=/d' "$working_dir/../ufw-docker") help
}
test-ufw-docker-init-legacy-assert() {
iptables --version
test -n chaifeng/ufw-docker-agent:090502-legacy
trap on-exit EXIT INT TERM QUIT ABRT ERR
@dryrun cat
}
test-ufw-docker-init-nf_tables() {
@mockfalse grep -F '(legacy)'
@source <(@sed '/PATH=/d' "$working_dir/../ufw-docker") help
}
test-ufw-docker-init-nf_tables-assert() {
iptables --version
test -n chaifeng/ufw-docker-agent:090502-nf_tables
trap on-exit EXIT INT TERM QUIT ABRT ERR
@dryrun cat
}
test-ufw-docker-init() {
UFW_DOCKER_AGENT_IMAGE=chaifeng/ufw-docker-agent:100917
@source <(@sed '/PATH=/d' "$working_dir/../ufw-docker") help
}
test-ufw-docker-init-assert() {
test -n chaifeng/ufw-docker-agent:100917
trap on-exit EXIT INT TERM QUIT ABRT ERR
@dryrun cat
}
test-ufw-docker-help() {
ufw-docker help
}
test-ufw-docker-help-assert() {
ufw-docker--help
}
test-ufw-docker-without-parameters() {
ufw-docker
}
test-ufw-docker-without-parameters-assert() {
test-ufw-docker-help-assert
}
test-ufw-is-disabled() {
@mockfalse grep -Fq "Status: active"
@mock iptables --version === @stdout 'iptables v1.8.4 (legacy)'
ufw-docker
}
test-ufw-is-disabled-assert() {
die "UFW is disabled or you are not root user, or mismatched iptables legacy/nf_tables, current iptables v1.8.4 (legacy)"
ufw-docker--help
}
test-docker-is-installed() {
@mockfalse docker -v
ufw-docker
}
test-docker-is-installed-assert() {
die "Docker executable not found."
ufw-docker--help
}
test-ufw-docker-status() {
ufw-docker status
}
test-ufw-docker-status-assert() {
ufw-docker--status
}
test-ufw-docker-install() {
ufw-docker install
}
test-ufw-docker-install-assert() {
ufw-docker--install
}
test-ufw-docker-install--docker-subnets() {
ufw-docker install --docker-subnets
}
test-ufw-docker-install--docker-subnets-assert() {
ufw-docker--install --docker-subnets
}
test-ufw-docker-check() {
ufw-docker check
}
test-ufw-docker-check-assert() {
ufw-docker--check
}
test-ufw-docker-check--docker-subnets() {
ufw-docker check --docker-subnets
}
test-ufw-docker-check--docker-subnets-assert() {
ufw-docker--check --docker-subnets
}
test-ufw-docker-service() {
ufw-docker service allow httpd
}
test-ufw-docker-service-assert() {
ufw-docker--service allow httpd
}
test-ufw-docker-raw-command() {
ufw-docker raw-command status
}
test-ufw-docker-raw-command-assert() {
ufw-docker--raw-command status
}
test-ufw-docker-add-service-rule() {
ufw-docker add-service-rule httpd 80/tcp
}
test-ufw-docker-add-service-rule-assert() {
ufw-docker--add-service-rule httpd 80/tcp
}
test-ASSERT-FAIL-ufw-docker-delete-must-have-parameters() {
ufw-docker delete
}
test-ASSERT-FAIL-ufw-docker-list-must-have-parameters() {
ufw-docker list
}
test-ASSERT-FAIL-ufw-docker-allow-must-have-parameters() {
ufw-docker allow
}
test-ASSERT-FAIL-ufw-docker-delete-httpd-but-it-doesnt-exist() {
@mockfalse ufw-docker--instance-name httpd
ufw-docker delete httpd
}
test-ASSERT-FAIL-ufw-docker-list-httpd-but-it-doesnt-exist() {
@mockfalse ufw-docker--instance-name httpd
ufw-docker list httpd
}
test-ASSERT-FAIL-ufw-docker-allow-httpd-but-it-doesnt-exist() {
@mockfalse ufw-docker--instance-name httpd
ufw-docker allow httpd
}
test-ufw-docker-list-httpd() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker list httpd
}
test-ufw-docker-list-httpd-assert() {
ufw-docker--list httpd-container-name "" tcp ""
}
test-ufw-docker-allow-httpd() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker allow httpd
}
test-ufw-docker-allow-httpd-assert() {
ufw-docker--allow httpd-container-name "" tcp ""
}
test-ufw-docker-allow-httpd-80() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker allow httpd 80
}
test-ufw-docker-allow-httpd-80-assert() {
ufw-docker--allow httpd-container-name 80 tcp ""
}
test-ufw-docker-allow-httpd-80tcp() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker allow httpd 80/tcp
}
test-ufw-docker-allow-httpd-80tcp-assert() {
ufw-docker--allow httpd-container-name 80 tcp ""
}
test-ufw-docker-allow-httpd-80udp() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker allow httpd 80/udp
}
test-ufw-docker-allow-httpd-80udp-assert() {
ufw-docker--allow httpd-container-name 80 udp ""
}
test-ASSERT-FAIL-ufw-docker-allow-httpd-INVALID-port() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
@mock die 'invalid port syntax: "invalid".' === exit 1
ufw-docker allow httpd invalid
}
test-ufw-docker-delete-allow-httpd() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker delete allow httpd
}
test-ufw-docker-delete-allow-httpd-assert() {
ufw-docker--delete httpd-container-name "" tcp ""
}
test-ASSERT-FAIL-ufw-docker-delete-only-supports-allowed-rules() {
@mock ufw-docker--instance-name httpd === @stdout httpd-container-name
ufw-docker delete non-allow
}
test-ASSERT-FAIL-ufw-docker-delete-only-supports-allowed-rules-assert() {
die "\"delete\" command only support removing allowed rules"
}
function setup-ufw-docker--allow() {
load-ufw-docker-function ufw-docker--allow
@mocktrue docker inspect instance-name
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3"
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
}
function setup-IPv6-ufw-docker--allow() {
load-ufw-docker-function ufw-docker--allow
@mocktrue docker inspect instance-name
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "default fd00:cf::42"
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
}
function setup-ufw-docker--allow--multinetwork() {
load-ufw-docker-function ufw-docker--allow
@mocktrue docker inspect instance-name
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "awesomenet 172.19.0.7"
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
}
function setup-IPv6-ufw-docker--allow--multinetwork() {
load-ufw-docker-function ufw-docker--allow
@mocktrue docker inspect instance-name
@mock docker inspect --format '{{range $name, $net := .NetworkSettings.Networks}}{{if $net.IPAddress}}{{$name}} {{$net.IPAddress}}{{"\n"}}{{end}}{{if $net.GlobalIPv6Address}}{{$name}} {{$net.GlobalIPv6Address}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout "default 172.18.0.3" "default fd00:cf::42" "awesomenet 172.19.0.7" "awesomenet fd00:cf::207"
@mock docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{with $conf}}{{$p}}{{"\n"}}{{end}}{{end}}' instance-name === @stdout 5000/tcp 8080/tcp 5353/udp
}
test-ufw-docker--allow-instance-not-found() {
setup-ufw-docker--allow
@mockfalse docker inspect invalid-instance
@mockfalse die "Docker instance \"invalid-instance\" doesn't exist."
ufw-docker--allow invalid-instance 80 tcp
}
test-ufw-docker--allow-instance-not-found-assert() {
@do-nothing
@fail
}
test-ufw-docker--allow-instance-but-the-port-not-match() {
setup-ufw-docker--allow
ufw-docker--allow instance-name 80 tcp
}
test-ufw-docker--allow-instance-but-the-port-not-match-assert() {
@do-nothing
@fail
}
test-ufw-docker--allow-instance-but-the-proto-not-match() {
setup-ufw-docker--allow
ufw-docker--allow instance-name 5353 tcp
}
test-ufw-docker--allow-instance-but-the-proto-not-match-assert() {
@do-nothing
@fail
}
test-ufw-docker--allow-instance-and-match-the-port() {
setup-ufw-docker--allow
ufw-docker--allow instance-name 5000 tcp
}
test-ufw-docker--allow-instance-and-match-the-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
}
test-ufw-docker--allow-instance-all-published-port() {
setup-ufw-docker--allow
ufw-docker--allow instance-name "" ""
}
test-ufw-docker--allow-instance-all-published-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
}
test-ufw-docker--allow-instance-all-published-tcp-port() {
setup-ufw-docker--allow
ufw-docker--allow instance-name "" tcp
}
test-ufw-docker--allow-instance-all-published-tcp-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default # FIXME
}
test-ufw-docker--allow-instance-all-published-port-multinetwork() {
setup-ufw-docker--allow--multinetwork
ufw-docker--allow instance-name "" ""
}
test-ufw-docker--allow-instance-all-published-port-multinetwork-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
}
test-ufw-docker--allow-instance-all-published-port-multinetwork-select-network() {
setup-ufw-docker--allow--multinetwork
ufw-docker--allow instance-name "" "" awesomenet
}
test-ufw-docker--allow-instance-all-published-port-multinetwork-select-network-assert() {
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
}
test-IPv6-ufw-docker--allow-instance-and-match-the-port() {
setup-IPv6-ufw-docker--allow
ufw-docker--allow instance-name 5000 tcp
}
test-IPv6-ufw-docker--allow-instance-and-match-the-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
}
test-IPv6-ufw-docker--allow-instance-all-published-port() {
setup-IPv6-ufw-docker--allow
ufw-docker--allow instance-name "" ""
}
test-IPv6-ufw-docker--allow-instance-all-published-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default
}
test-IPv6-ufw-docker--allow-instance-all-published-tcp-port() {
setup-IPv6-ufw-docker--allow
ufw-docker--allow instance-name "" tcp
}
test-IPv6-ufw-docker--allow-instance-all-published-tcp-port-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default # FIXME
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default # FIXME
}
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork() {
setup-IPv6-ufw-docker--allow--multinetwork
ufw-docker--allow instance-name "" ""
}
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-assert() {
ufw-docker--add-rule instance-name 172.18.0.3 5000 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5000 tcp default
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5000 tcp awesomenet
ufw-docker--add-rule instance-name 172.18.0.3 8080 tcp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 8080 tcp default
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 8080 tcp awesomenet
ufw-docker--add-rule instance-name 172.18.0.3 5353 udp default
ufw-docker--add-rule instance-name/v6 fd00:cf::42 5353 udp default
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5353 udp awesomenet
}
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-select-network() {
setup-IPv6-ufw-docker--allow--multinetwork
ufw-docker--allow instance-name "" "" awesomenet
}
test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-select-network-assert() {
ufw-docker--add-rule instance-name 172.19.0.7 5000 tcp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5000 tcp awesomenet
ufw-docker--add-rule instance-name 172.19.0.7 8080 tcp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 8080 tcp awesomenet
ufw-docker--add-rule instance-name 172.19.0.7 5353 udp awesomenet
ufw-docker--add-rule instance-name/v6 fd00:cf::207 5353 udp awesomenet
}
test-ufw-docker--add-rule-a-non-existing-rule() {
@mockfalse ufw-docker--list webapp 5000 tcp ""
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp
}
test-ufw-docker--add-rule-a-non-existing-rule-assert() {
ufw route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp"
}
test-ufw-docker--add-rule-a-non-existing-rule-with-network() {
@mockfalse ufw-docker--list webapp 5000 tcp default
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp default
}
test-ufw-docker--add-rule-a-non-existing-rule-with-network-assert() {
ufw route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default"
}
test-ufw-docker--add-rule-modify-an-existing-rule() {
@mocktrue ufw-docker--list webapp 5000 tcp default
@mock ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default" === @echo
@mockfalse grep "^Skipping"
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp default
}
test-ufw-docker--add-rule-modify-an-existing-rule-assert() {
ufw-docker--delete webapp 5000 tcp default
ufw route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp default"
}
test-IPv6-ufw-docker--add-rule-modify-an-existing-rule() {
@mocktrue ufw-docker--list webapp/v6 5000 tcp default
@mock ufw --dry-run route allow proto tcp from any to fd00:cf::42 port 5000 comment "allow webapp/v6 5000/tcp default" === @echo
@mockfalse grep "^Skipping"
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp/v6 fd00:cf::42 5000 tcp default
}
test-IPv6-ufw-docker--add-rule-modify-an-existing-rule-assert() {
ufw-docker--delete webapp/v6 5000 tcp default
ufw route allow proto tcp from any to fd00:cf::42 port 5000 comment "allow webapp/v6 5000/tcp default"
}
test-ufw-docker--add-rule-skip-an-existing-rule() {
@mocktrue ufw-docker--list webapp 5000 tcp ""
@mocktrue ufw --dry-run route allow proto tcp from any to 172.18.0.4 port 5000 comment "allow webapp 5000/tcp"
@mocktrue grep "^Skipping"
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp 172.18.0.4 5000 tcp ""
}
test-ufw-docker--add-rule-skip-an-existing-rule-assert() {
@do-nothing
}
test-ufw-docker--add-rule-modify-an-existing-rule-without-port() {
@mocktrue ufw-docker--list webapp "" tcp ""
@mock ufw --dry-run route allow proto tcp from any to 172.18.0.4 comment "allow webapp" === @echo
@mockfalse grep "^Skipping"
@ignore echo
load-ufw-docker-function ufw-docker--add-rule
ufw-docker--add-rule webapp 172.18.0.4 "" tcp ""
}
test-ufw-docker--add-rule-modify-an-existing-rule-without-port-assert() {
ufw-docker--delete webapp "" tcp ""
ufw route allow proto tcp from any to 172.18.0.4 comment "allow webapp"
}
test-ufw-docker--instance-name-found-a-name() {
@mock docker inspect --format="{{.Name}}" foo
@mock sed -e 's,^/,,'
@mockfalse grep "^$GREP_REGEXP_NAME\$"
@mock echo -n foo
load-ufw-docker-function ufw-docker--instance-name
ufw-docker--instance-name foo
}
test-ufw-docker--instance-name-found-a-name-assert() {
docker inspect --format="{{.Name}}" foo
@dryrun echo -n foo
}
test-ufw-docker--instance-name-found-an-id() {
@mock docker inspect --format="{{.Name}}" fooid
@mock sed -e 's,^/,,'
@mockfalse grep "^$GREP_REGEXP_NAME\$"
@mock echo -n fooid
load-ufw-docker-function ufw-docker--instance-name
ufw-docker--instance-name fooid
}
test-ufw-docker--instance-name-found-an-id-assert() {
docker inspect --format="{{.Name}}" fooid
@dryrun echo -n fooid
}
function mock-ufw-status-numbered-foo() {
@mock ufw status numbered === @echo "Status: active
To Action From
-- ------ ----
[ 1] OpenSSH ALLOW IN Anywhere
[ 2] Anywhere ALLOW IN 192.168.56.128/28
[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge
[ 4] 172.20.0.3 80/tcp ALLOW FWD Anywhere # allow bar 80/tcp bar-external
[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal
[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp
[ 7] 172.18.0.2 29090/tcp ALLOW FWD Anywhere # allow id111111 29090/tcp
[ 8] 172.18.0.2 48080/tcp ALLOW FWD Anywhere # allow id222222 48080/tcp
[ 9] 172.18.0.2 40080/tcp ALLOW FWD Anywhere # allow id333333 40080/tcp
[10] OpenSSH (v6) ALLOW IN Anywhere (v6)
[11] Anywhere (v6) ALLOW IN fd00:a:b:0:cafe::/80
[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge
[13] fd05:8f23:c937:2::3 80/tcp ALLOW FWD Anywhere (v6) # allow bar/v6 80/tcp bar-external
[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal
[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp
"
}
test-ufw-docker--status() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow [-_.[:alnum:]]\+\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
load-ufw-docker-function ufw-docker--list
load-ufw-docker-function ufw-docker--status
ufw-docker--status
}
test-ufw-docker--status-assert() {
test-ufw-docker--list-all-assert
}
test-ufw-docker--list-all() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow [-_.[:alnum:]]\+\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list
}
test-ufw-docker--list-all-assert() {
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
@stdout "[ 4] 172.20.0.3 80/tcp ALLOW FWD Anywhere # allow bar 80/tcp bar-external"
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
@stdout "[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp"
@stdout "[ 7] 172.18.0.2 29090/tcp ALLOW FWD Anywhere # allow id111111 29090/tcp"
@stdout "[ 8] 172.18.0.2 48080/tcp ALLOW FWD Anywhere # allow id222222 48080/tcp"
@stdout "[ 9] 172.18.0.2 40080/tcp ALLOW FWD Anywhere # allow id333333 40080/tcp"
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
@stdout "[13] fd05:8f23:c937:2::3 80/tcp ALLOW FWD Anywhere (v6) # allow bar/v6 80/tcp bar-external"
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
@stdout "[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp"
}
test-ufw-docker--list-name() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\?\( [[:digit:]]\+/\(tcp\|udp\)\( [-_.[:alnum:]]\+\)\?\)\?$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo
}
test-ufw-docker--list-name-assert() {
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
@stdout "[ 6] 172.17.0.3 53/tcp ALLOW FWD Anywhere # allow foo 53/tcp"
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
@stdout "[15] fd00:a:b:deaf::3 53/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 53/tcp"
}
test-ufw-docker--list-name-udp() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\? [[:digit:]]\+/udp\( [-_.[:alnum:]]\+\)\?$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo "" udp
}
test-ufw-docker--list-name-udp-assert() {
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
}
test-ufw-docker--list-name-80-_-bridge() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\? 80/tcp bridge$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo 80 "" bridge
}
test-ufw-docker--list-name-80-_-bridge-assert() {
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
}
test-ufw-docker--list-name-53-udp() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\? 53/udp\( [-_.[:alnum:]]\+\)\?$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo 53 udp
}
test-ufw-docker--list-name-53-udp-assert() {
@stdout "[ 5] 172.17.0.3 53/udp ALLOW FWD Anywhere # allow foo 53/udp foo-internal"
@stdout "[14] fd00:a:b:deaf::3 53/udp ALLOW FWD Anywhere (v6) # allow foo/v6 53/udp foo-internal"
}
test-ufw-docker--list-grep-with-incorrect-network() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\? 53/udp incorrect-network$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo 53 udp incorrect-network
}
test-ufw-docker--list-grep-with-incorrect-network-assert() {
@fail
}
test-ufw-docker--list-foo-80-_-_() {
mock-ufw-status-numbered-foo
@allow-real grep '# allow foo\(/v6\)\? 80/tcp\( [-_.[:alnum:]]\+\)\?$'
load-ufw-docker-function ufw-docker--list
ufw-docker--list foo 80
}
test-ufw-docker--list-foo-80-_-_-assert() {
@stdout "[ 3] 172.17.0.3 80/tcp ALLOW FWD Anywhere # allow foo 80/tcp bridge"
@stdout "[12] fd00:a:b:deaf::3 80/tcp ALLOW FWD Anywhere (v6) # allow foo/v6 80/tcp bridge"
}
test-ufw-docker--list-number() {
@mocktrue ufw-docker--list foo 53 udp
load-ufw-docker-function ufw-docker--list-number
ufw-docker--list-number foo 53 udp
}
test-ufw-docker--list-number-assert() {
sed -e 's/^\[[[:blank:]]*\([[:digit:]]\+\)\].*/\1/'
}
test-ufw-docker--delete-empty-result() {
@mock ufw-docker--list-number webapp 80 tcp === @stdout ""
@mockpipe sort -rn
load-ufw-docker-function ufw-docker--delete
ufw-docker--delete webapp 80 tcp
}
test-ufw-docker--delete-empty-result-assert() {
@do-nothing
}
test-ufw-docker--delete-all() {
@mock ufw-docker--list-number webapp 80 tcp === @stdout 5 8 9
@mockpipe sort -rn
@ignore echo
load-ufw-docker-function ufw-docker--delete
ufw-docker--delete webapp 80 tcp
}
test-ufw-docker--delete-all-assert() {
ufw delete 5
ufw delete 8
ufw delete 9
}
test-ufw-docker--check-install_ipv4() {
@mock mktemp === @stdout /tmp/after_rules_tmp
@mock sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
@mock tee "/tmp/after_rules_tmp"
@capture tee -a /tmp/after_rules_tmp
@allow-real cat
load-ufw-docker-function ufw-docker--check-install
ufw-docker--check-install
}
test-ufw-docker--check-install_ipv4-assert() {
rm-on-exit /tmp/after_rules_tmp
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
@assert-capture tee -a /tmp/after_rules_tmp <<\EOF
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j RETURN
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP
COMMIT
# END UFW AND DOCKER
EOF
diff -u --color=auto /etc/ufw/after.rules /tmp/after_rules_tmp
}
test-ufw-docker--check-install_ipv4-subnets() {
@mock ufw-docker--list-docker-subnets IPv4 192.168.56.128/28 172.16.0.0/12 === @stdout "172.16.0.0/12" "192.168.56.128/28"
@mock mktemp === @stdout /tmp/after_rules_tmp
@mock sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
@mock tee "/tmp/after_rules_tmp"
@capture tee -a /tmp/after_rules_tmp
@allow-real cat
load-ufw-docker-function ufw-docker--check-install
ufw-docker--check-install --docker-subnets 192.168.56.128/28 172.16.0.0/12
}
test-ufw-docker--check-install_ipv4-subnets-assert() {
rm-on-exit /tmp/after_rules_tmp
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" /etc/ufw/after.rules
@assert-capture tee -a /tmp/after_rules_tmp <<\EOF
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.56.128/28
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.56.128/28
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.56.128/28
-A DOCKER-USER -j RETURN
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP
COMMIT
# END UFW AND DOCKER
EOF
diff -u --color=auto /etc/ufw/after.rules /tmp/after_rules_tmp
}