mirror of
https://github.com/chaifeng/ufw-docker.git
synced 2025-07-09 19:16:12 +02:00
Support multiple ports in ufw-docker service allow
This commit is contained in:
parent
359d20d87c
commit
b06afc13ef
7 changed files with 611 additions and 115 deletions
|
@ -1,6 +1,6 @@
|
|||
FROM ubuntu:24.04
|
||||
|
||||
ARG docker_version="27.3.1"
|
||||
ARG docker_version="28.3.1"
|
||||
ARG use_iptables_legacy=false
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
|
|
@ -681,6 +681,8 @@ UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管
|
|||
|
||||
ufw-docker service delete allow web
|
||||
|
||||
ufw-docker service delete allow web 80/tcp
|
||||
|
||||
### 试试
|
||||
|
||||
我们使用 [Vagrant](https://www.vagrantup.com/) 来创建一个本地的测试环境。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
[[ -n "${DEBUG:-}" ]] && set -x
|
||||
[[ "${DEBUG:-}" = true ]] && set -x
|
||||
[[ 0 -eq "$#" ]] && set -- start
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
|
@ -10,8 +10,12 @@ function ufw-allow-or-deny-service() {
|
|||
declare id="$1"
|
||||
declare port="$2"
|
||||
|
||||
if [[ "$port" = deny ]]; then
|
||||
run-ufw-docker delete allow "$id"
|
||||
if [[ "$port" = deny || "$port" = */deny ]]; then
|
||||
port="${port%deny}"
|
||||
port="${port%/}"
|
||||
declare -a opts=("$id")
|
||||
[[ -z "$port" ]] || opts+=("$port")
|
||||
run-ufw-docker delete allow "${opts[@]}"
|
||||
else
|
||||
run-ufw-docker add-service-rule "$id" "$port"
|
||||
fi
|
||||
|
@ -22,8 +26,14 @@ function update-ufw-rules() {
|
|||
-e 's/^declare -x ufw_public_//' \
|
||||
-e 's/="/ /' \
|
||||
-e 's/"$//' |
|
||||
while read -r id port; do
|
||||
ufw-allow-or-deny-service "${id}" "${port#*/}"
|
||||
while read -r id ruleset; do
|
||||
declare -a rules=( $(tr ',' '\n' <<< "$ruleset") )
|
||||
for rule in "${rules[@]}"; do
|
||||
[[ "$rule" = */deny ]] && ufw-allow-or-deny-service "${id}" "${rule#*/}"
|
||||
done
|
||||
for rule in "${rules[@]}"; do
|
||||
[[ "$rule" = */deny ]] || ufw-allow-or-deny-service "${id}" "${rule#*/}"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 27885eb79c11e4652dede994c886ae5f9e30994f
|
||||
Subproject commit 871528a805b21e3c4432e4c23cacc3c4f4ddfc39
|
|
@ -6,9 +6,8 @@ source "$working_dir"/bach/bach.sh
|
|||
|
||||
@setup {
|
||||
set -euo pipefail
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
ufw_docker_agent_image=chaifeng/ufw-docker-agent:181005
|
||||
ufw_docker_agent_image=chaifeng/ufw-docker-agent:090502
|
||||
}
|
||||
|
||||
@setup-test {
|
||||
|
@ -19,9 +18,17 @@ source "$working_dir"/bach/bach.sh
|
|||
@ignore echo
|
||||
@ignore err
|
||||
|
||||
DEFAULT_PROTO=tcp
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
UFW_DOCKER_AGENT_IMAGE=chaifeng/ufw-docker-agent:090502
|
||||
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")
|
||||
|
||||
DEBUG=false
|
||||
|
||||
unset RANDOM
|
||||
RANDOM=42
|
||||
|
||||
@allow-real sed -e '/^ufw_public_/!d' -e 's/^ufw_public_//' -e 's/=/ /'
|
||||
@allow-real tr ',' '\n'
|
||||
@allow-real grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
}
|
||||
|
||||
function die() {
|
||||
|
@ -110,6 +117,26 @@ test-ufw-docker--service-delete-allow-webapp-assert() {
|
|||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-tcp() {
|
||||
load-ufw-docker-function ufw-docker--service
|
||||
|
||||
ufw-docker--service delete allow webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-tcp-assert() {
|
||||
ufw-docker--service-delete webapp 8080/tcp
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-allow-webapp-8080() {
|
||||
load-ufw-docker-function ufw-docker--service
|
||||
|
||||
ufw-docker--service delete allow webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-allow-webapp-8080-assert() {
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--get-service-id() {
|
||||
load-ufw-docker-function ufw-docker--get-service-id
|
||||
ufw-docker--get-service-id database
|
||||
|
@ -129,8 +156,6 @@ test-ufw-docker--get-service-name-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-invalid-port-syntax() {
|
||||
@mockfalse grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp invalid-port
|
||||
}
|
||||
|
@ -141,7 +166,6 @@ test-ufw-docker--service-allow-invalid-port-syntax-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-an-non-existed-service() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id web404 === @stdout ""
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
|
@ -154,7 +178,6 @@ test-ufw-docker--service-allow-an-non-existed-service-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-without-ports-published() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id private-web === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name private-web === @stdout private-web
|
||||
@mock ufw-docker--list-service-ports private-web === @stdout ""
|
||||
|
@ -169,7 +192,6 @@ test-ufw-docker--service-allow-a-service-without-ports-published-assert() {
|
|||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-while-agent-not-running() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
|
@ -182,15 +204,14 @@ test-ufw-docker--service-allow-a-service-while-agent-not-running-assert() {
|
|||
docker service create --name ufw-docker-agent --mode global \
|
||||
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
|
||||
--mount type=bind,source=/etc/ufw,target=/etc/ufw,readonly=true \
|
||||
--env ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env DEBUG="false" \
|
||||
--env "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
"chaifeng/ufw-docker-agent:181005"
|
||||
"chaifeng/ufw-docker-agent:090502"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-add-new-env() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
|
@ -202,16 +223,15 @@ test-ufw-docker--service-allow-a-service-add-new-env() {
|
|||
}
|
||||
test-ufw-docker--service-allow-a-service-add-new-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
--image "chaifeng/ufw-docker-agent:181005" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-update-a-env() {
|
||||
@mocktrue grep -E '^[0-9]+(/(tcp|udp))?$'
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "53 53/udp" "80 80/tcp" "8080 8080/tcp"
|
||||
|
@ -223,11 +243,60 @@ test-ufw-docker--service-allow-a-service-update-a-env() {
|
|||
}
|
||||
test-ufw-docker--service-allow-a-service-update-a-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:181005" \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--image "chaifeng/ufw-docker-agent:181005" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-allow-a-service-add-value-to-an-env() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "5353 53/udp" "8080 80/tcp" "18080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "a_different_id webapp/8080/tcp" "abcd1234 webapp/5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp 80/tcp
|
||||
ufw-docker--service-allow webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-allow-a-service-add-value-to-an-env-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/8080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/18080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
test-ufw-docker--service-allow-a-service-denied-port() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout abcd1234
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "5353 53/udp" "8080 80/tcp" "18080 8080/tcp"
|
||||
@mocktrue docker service inspect ufw-docker-agent
|
||||
@mock ufw-docker--get-env-list === @stdout "a_different_id webapp/8080/tcp" "abcd1234 webapp/8080/tcp/deny" "abcd1234 webapp/5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-allow
|
||||
ufw-docker--service-allow webapp 80/tcp
|
||||
}
|
||||
test-ufw-docker--service-allow-a-service-denied-port-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="chaifeng/ufw-docker-agent:090502" \
|
||||
--env-add DEBUG="false" \
|
||||
--env-rm "ufw_public_a_different_id" \
|
||||
--env-add "ufw_public_abcd1234=webapp/8080/tcp,webapp/5353/udp" \
|
||||
--image "chaifeng/ufw-docker-agent:090502" \
|
||||
ufw-docker-agent
|
||||
}
|
||||
|
||||
|
@ -236,27 +305,50 @@ test-ufw-docker--get-env-list() {
|
|||
@mock docker service inspect ufw-docker-agent \
|
||||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' \
|
||||
=== @stdout \
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_zv6esvmwnmmgnlauqn7m77jo4=webapp/9090/tcp" \
|
||||
"OTHER_ENV=blabla"
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_id111111=webapp/9090/tcp" \
|
||||
"ufw_public_id222222=foo/2222/udp" \
|
||||
"OTHER_ENV=blabla"
|
||||
|
||||
@mock sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /' === @real sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /'
|
||||
@allow-real sed "s/^/id111111 /g"
|
||||
@allow-real sed "s/^/id222222 /g"
|
||||
|
||||
load-ufw-docker-function ufw-docker--get-env-list
|
||||
ufw-docker--get-env-list
|
||||
}
|
||||
test-ufw-docker--get-env-list-assert() {
|
||||
@stdout "zv6esvmwnmmgnlauqn7m77jo4 webapp/9090/tcp"
|
||||
@stdout "id111111 webapp/9090/tcp"
|
||||
@stdout "id222222 foo/2222/udp"
|
||||
}
|
||||
|
||||
test-ufw-docker--get-env-list-multiple() {
|
||||
@mock docker service inspect ufw-docker-agent \
|
||||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' \
|
||||
=== @stdout \
|
||||
"ufw_docker_agent_image=192.168.56.130:5000/chaifeng/ufw-docker-agent:test" \
|
||||
"DEBUG=true" \
|
||||
"ufw_public_id111111=webapp/9090/tcp,webapp/8888/tcp,webapp/5555/udp" \
|
||||
"ufw_public_id222222=foo/2222/udp,foo/3333/tcp" \
|
||||
"OTHER_ENV=blabla"
|
||||
|
||||
@allow-real sed "s/^/id111111 /g"
|
||||
@allow-real sed "s/^/id222222 /g"
|
||||
|
||||
load-ufw-docker-function ufw-docker--get-env-list
|
||||
ufw-docker--get-env-list
|
||||
}
|
||||
test-ufw-docker--get-env-list-multiple-assert() {
|
||||
@stdout "id111111 webapp/9090/tcp"
|
||||
@stdout "id111111 webapp/8888/tcp"
|
||||
@stdout "id111111 webapp/5555/udp"
|
||||
@stdout "id222222 foo/2222/udp"
|
||||
@stdout "id222222 foo/3333/tcp"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-no-matches() {
|
||||
@mock ufw-docker--get-env-list === @stdout "ffff111 foo/80/tcp" "eeee2222 bar/53/udp"
|
||||
@mockfalse ufw-docker--get-service-id webapp
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
|
@ -266,9 +358,15 @@ test-ufw-docker--service-delete-no-matches-assert() {
|
|||
@fail
|
||||
}
|
||||
|
||||
function mock-abcd1234-webapp() {
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--get-service-id webapp === @stdout "abcd1234"
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "22 2222/tcp" "80 8080/tcp" "53 5353/udp"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches() {
|
||||
@mock ufw-docker--get-env-list === @stdout "ffff111 foo/80/tcp" "eeee2222 bar/53/udp" "abcd1234 webapp/5000/tcp"
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/22/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
|
@ -282,6 +380,130 @@ test-ufw-docker--service-delete-matches-assert() {
|
|||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/22/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny,webapp/53/udp,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-but-no-previous-rule() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 2222
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-but-no-previous-rule-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/22/tcp/deny,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080/tcp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/80/tcp/deny" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair2() {
|
||||
mock-abcd1234-webapp
|
||||
@mock ufw-docker--get-env-list === @stdout "xxx 888/tcp" "abcd1234 webapp/80/tcp" "abcd1234 webapp/53/udp" "abcd1234 webapp/53/tcp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 5353/udp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-port-proto-pair2-assert() {
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
--env-add "ufw_public_abcd1234=webapp/53/udp/deny,webapp/80/tcp,webapp/53/tcp" \
|
||||
--env-add "DEBUG=false" \
|
||||
--image "${ufw_docker_agent_image}" \
|
||||
"${ufw_docker_agent}"
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-port() {
|
||||
mock-abcd1234-webapp
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 3333
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-port-assert() {
|
||||
@do-nothing
|
||||
@fail
|
||||
}
|
||||
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-protocal() {
|
||||
@mock ufw-docker--get-service-id webapp === @stdout "abcd1234"
|
||||
@mock ufw-docker--get-service-name webapp === @stdout webapp
|
||||
@mock ufw-docker--list-service-ports webapp === @stdout "22 2222/tcp" "80 8080/tcp" "53 5353/udp"
|
||||
|
||||
load-ufw-docker-function ufw-docker--service-delete
|
||||
ufw-docker--service-delete webapp 8080/udp
|
||||
}
|
||||
test-ufw-docker--service-delete-matches-with-a-not-matched-protocal-assert() {
|
||||
@do-nothing
|
||||
@fail
|
||||
}
|
||||
|
||||
test-ufw-docker--list-service-ports() {
|
||||
load-ufw-docker-function ufw-docker--list-service-ports
|
||||
ufw-docker--list-service-ports foo
|
||||
|
@ -289,3 +511,52 @@ test-ufw-docker--list-service-ports() {
|
|||
test-ufw-docker--list-service-ports-assert() {
|
||||
docker service inspect foo --format '{{range .Endpoint.Spec.Ports}}{{.PublishedPort}} {{.TargetPort}}/{{.Protocol}}{{"\n"}}{{end}}'
|
||||
}
|
||||
|
||||
function setup-mock-for-testing-docker-entrypoint() {
|
||||
@mock date '+%Y%m%d%H%M%S' === @stdout 200902140731
|
||||
|
||||
declare -gx ufw_public_id111111=alpha/80/tcp
|
||||
declare -gx ufw_public_id222222=beta/deny
|
||||
declare -gx ufw_public_id333333=gamma/8080/tcp/deny,gamma/5353/udp
|
||||
|
||||
@allow-real sed -e '/^declare -x ufw_public_/!d' -e 's/^declare -x ufw_public_//' -e 's/="/ /' -e 's/"$//'
|
||||
@allow-real tr ',' '\n'
|
||||
}
|
||||
|
||||
test-dockerentrypoint() {
|
||||
setup-mock-for-testing-docker-entrypoint
|
||||
declare -x ufw_public_id333333=gamma/8080/tcp/deny,gamma/5353/udp
|
||||
|
||||
@run "$working_dir"/../docker-entrypoint.sh update-ufw-rules
|
||||
}
|
||||
test-dockerentrypoint-assert() {
|
||||
declare -a docker_opts=(run --rm -t --name ufw-docker-agent-42-200902140731
|
||||
--cap-add NET_ADMIN --network host --env DEBUG=false
|
||||
-v /var/run/docker.sock:/var/run/docker.sock
|
||||
-v /etc/ufw:/etc/ufw
|
||||
chaifeng/ufw-docker-agent:090502
|
||||
)
|
||||
docker "${docker_opts[@]}" add-service-rule id111111 80/tcp
|
||||
docker "${docker_opts[@]}" delete allow id222222
|
||||
docker "${docker_opts[@]}" delete allow id333333 8080/tcp
|
||||
docker "${docker_opts[@]}" add-service-rule id333333 5353/udp
|
||||
}
|
||||
|
||||
test-dockerentrypoint-deny-first() {
|
||||
setup-mock-for-testing-docker-entrypoint
|
||||
declare -x ufw_public_id333333=gamma/5353/udp,gamma/8080/tcp/deny
|
||||
|
||||
@run "$working_dir"/../docker-entrypoint.sh update-ufw-rules
|
||||
}
|
||||
test-dockerentrypoint-deny-first-assert() {
|
||||
declare -a docker_opts=(run --rm -t --name ufw-docker-agent-42-200902140731
|
||||
--cap-add NET_ADMIN --network host --env DEBUG=false
|
||||
-v /var/run/docker.sock:/var/run/docker.sock
|
||||
-v /etc/ufw:/etc/ufw
|
||||
chaifeng/ufw-docker-agent:090502
|
||||
)
|
||||
docker "${docker_opts[@]}" add-service-rule id111111 80/tcp
|
||||
docker "${docker_opts[@]}" delete allow id222222
|
||||
docker "${docker_opts[@]}" delete allow id333333 8080/tcp
|
||||
docker "${docker_opts[@]}" add-service-rule id333333 5353/udp
|
||||
}
|
||||
|
|
|
@ -19,12 +19,10 @@ source "$working_dir"/bach/bach.sh
|
|||
@mock docker -v === @stdout Docker version 0.0.0, build dummy
|
||||
|
||||
@mockpipe remove_blank_lines
|
||||
@ignore echo
|
||||
#@ignore echo
|
||||
@ignore err
|
||||
|
||||
DEFAULT_PROTO=tcp
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -34,7 +32,6 @@ function ufw-docker() {
|
|||
|
||||
function load-ufw-docker-function() {
|
||||
set -euo pipefail
|
||||
|
||||
@load_function "$working_dir/../ufw-docker" "$1"
|
||||
}
|
||||
|
||||
|
@ -214,7 +211,7 @@ test-ufw-docker-list-httpd() {
|
|||
ufw-docker list httpd
|
||||
}
|
||||
test-ufw-docker-list-httpd-assert() {
|
||||
ufw-docker--list 'httpd-container-name\(/v6\)\?' "" tcp ""
|
||||
ufw-docker--list httpd-container-name "" tcp ""
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,7 +264,7 @@ test-ufw-docker-delete-allow-httpd() {
|
|||
ufw-docker delete allow httpd
|
||||
}
|
||||
test-ufw-docker-delete-allow-httpd-assert() {
|
||||
ufw-docker--delete 'httpd-container-name\(/v6\)\?' "" tcp ""
|
||||
ufw-docker--delete httpd-container-name "" tcp ""
|
||||
}
|
||||
|
||||
|
||||
|
@ -487,6 +484,7 @@ test-IPv6-ufw-docker--allow-instance-all-published-port-multinetwork-select-netw
|
|||
|
||||
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
|
||||
|
@ -497,6 +495,7 @@ test-ufw-docker--add-rule-a-non-existing-rule-assert() {
|
|||
|
||||
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
|
||||
|
@ -510,6 +509,7 @@ 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
|
||||
|
@ -525,6 +525,7 @@ 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
|
||||
|
@ -540,6 +541,7 @@ 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 ""
|
||||
|
@ -553,6 +555,7 @@ 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
|
||||
|
||||
|
@ -568,7 +571,7 @@ test-ufw-docker--add-rule-modify-an-existing-rule-without-port-assert() {
|
|||
test-ufw-docker--instance-name-found-a-name() {
|
||||
@mock docker inspect --format="{{.Name}}" foo
|
||||
@mock sed -e 's,^/,,'
|
||||
@mockfalse grep "^$GREP_REGEXP_INSTANCE_NAME\$"
|
||||
@mockfalse grep "^$GREP_REGEXP_NAME\$"
|
||||
|
||||
@mock echo -n foo
|
||||
|
||||
|
@ -584,77 +587,151 @@ test-ufw-docker--instance-name-found-a-name-assert() {
|
|||
test-ufw-docker--instance-name-found-an-id() {
|
||||
@mock docker inspect --format="{{.Name}}" fooid
|
||||
@mock sed -e 's,^/,,'
|
||||
@mockfalse grep "^$GREP_REGEXP_INSTANCE_NAME\$"
|
||||
@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() {
|
||||
@mocktrue ufw status numbered
|
||||
@mockfalse grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\( [[:graph:]]*\\)\$"
|
||||
@mockfalse grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\$"
|
||||
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() {
|
||||
grep "# allow foo\$"
|
||||
@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() {
|
||||
@mocktrue ufw status numbered
|
||||
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() {
|
||||
grep "# allow foo\\( [[:digit:]]\\+\\/\\(tcp\\|udp\\)\\)\\( [[:graph:]]*\\)\$"
|
||||
@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() {
|
||||
@mocktrue ufw status numbered
|
||||
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
|
||||
ufw-docker--list foo 80 "" bridge
|
||||
}
|
||||
test-ufw-docker--list-name-80-assert() {
|
||||
grep "# allow foo\\( 80\\/tcp\\)\\( [[:graph:]]*\\)\$"
|
||||
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-80-udp() {
|
||||
@mocktrue ufw status numbered
|
||||
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 80 udp
|
||||
ufw-docker--list foo 53 udp
|
||||
}
|
||||
test-ufw-docker--list-name-80-udp-assert() {
|
||||
grep "# allow foo\\( 80\\/udp\\)\\( [[:graph:]]*\\)\$"
|
||||
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-without-network() {
|
||||
@mocktrue ufw status numbered
|
||||
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 80 udp
|
||||
ufw-docker--list foo 53 udp incorrect-network
|
||||
}
|
||||
test-ufw-docker--list-grep-without-network-assert() {
|
||||
grep "# allow foo\\( 80\\/udp\\)\\( [[:graph:]]*\\)\$"
|
||||
test-ufw-docker--list-grep-with-incorrect-network-assert() {
|
||||
@fail
|
||||
}
|
||||
|
||||
|
||||
test-ufw-docker--list-grep-without-network-and-port() {
|
||||
@mocktrue ufw status numbered
|
||||
@mockfalse grep "# allow foo\\( 80\\/tcp\\)\\( [[:graph:]]*\\)\$"
|
||||
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-grep-without-network-and-port-assert() {
|
||||
grep "# allow foo\\( 80\\/tcp\\)\$"
|
||||
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"
|
||||
}
|
||||
|
||||
|
||||
|
@ -684,6 +761,7 @@ test-ufw-docker--delete-empty-result-assert() {
|
|||
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
|
||||
|
@ -693,3 +771,91 @@ test-ufw-docker--delete-all-assert() {
|
|||
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
|
||||
}
|
||||
|
|
133
ufw-docker
133
ufw-docker
|
@ -2,17 +2,21 @@
|
|||
set -euo pipefail
|
||||
[[ -n "${DEBUG:-}" ]] && set -x
|
||||
|
||||
LANG=en_US.UTF-8
|
||||
LANGUAGE=en_US:
|
||||
LC_ALL=en_US.UTF-8
|
||||
# UFW-DOCKER GLOBAL VARIABLES START #
|
||||
LC_ALL=C
|
||||
PATH="/bin:/usr/bin:/sbin:/usr/sbin:/snap/bin/"
|
||||
|
||||
GREP_REGEXP_INSTANCE_NAME="[-_.[:alnum:]]\\+"
|
||||
GREP_REGEXP_NAME="[-_.[:alnum:]]\\+"
|
||||
DEFAULT_PROTO=tcp
|
||||
ENV_VALUE_SPLITTER=','
|
||||
|
||||
ufw_docker_agent=ufw-docker-agent
|
||||
ufw_docker_agent_image="${UFW_DOCKER_AGENT_IMAGE:-chaifeng/${ufw_docker_agent}:250702-nf_tables}"
|
||||
|
||||
after_rules="/etc/ufw/after.rules"
|
||||
after6_rules="/etc/ufw/after6.rules"
|
||||
# UFW-DOCKER GLOBAL VARIABLES END #
|
||||
|
||||
if [[ "${ufw_docker_agent_image}" = *-@(legacy|nf_tables) ]]; then
|
||||
if iptables --version | grep -F '(legacy)' &>/dev/null; then
|
||||
ufw_docker_agent_image="${ufw_docker_agent_image%-*}-legacy"
|
||||
|
@ -24,31 +28,37 @@ fi
|
|||
test -n "$ufw_docker_agent_image"
|
||||
|
||||
function ufw-docker--status() {
|
||||
ufw-docker--list "$GREP_REGEXP_INSTANCE_NAME\(/v6\)\?"
|
||||
ufw-docker--list
|
||||
}
|
||||
|
||||
function ufw-docker--list() {
|
||||
local INSTANCE_NAME="$1"
|
||||
local INSTANCE_NAME="${1:-}"
|
||||
local INSTANCE_PORT="${2:-}"
|
||||
local PROTO="${3:-${DEFAULT_PROTO}}"
|
||||
local PROTO="${3:-}"
|
||||
local NETWORK="${4:-}"
|
||||
local params_count="$#"
|
||||
local _grep_regexp
|
||||
|
||||
if [[ -z "$INSTANCE_PORT" ]]; then
|
||||
[[ -n "${INSTANCE_NAME:-}" ]] || INSTANCE_NAME="$GREP_REGEXP_NAME"
|
||||
if [[ -z "${INSTANCE_PORT:-}" && -z "${PROTO:-}" && -z "${NETWORK-}" ]]; then
|
||||
INSTANCE_PORT="[[:digit:]]\\+"
|
||||
PROTO="\\(tcp\\|udp\\)"
|
||||
fi
|
||||
|
||||
if [[ -z "$NETWORK" ]]; then
|
||||
NETWORK="[[:graph:]]*"
|
||||
[[ -n "${PROTO:-}" ]] || PROTO="\\(tcp\\|udp\\)"
|
||||
_grep_regexp="\\( ${INSTANCE_PORT}/${PROTO}\\( ${GREP_REGEXP_NAME}\\)\\?\\)\\?"
|
||||
else
|
||||
[[ -n "${INSTANCE_PORT:-}" ]] || INSTANCE_PORT="[[:digit:]]\\+"
|
||||
[[ -n "${PROTO:-}" ]] || PROTO="${DEFAULT_PROTO}"
|
||||
if [[ -n "${NETWORK:-}" ]]; then
|
||||
NETWORK=" ${NETWORK}"
|
||||
else
|
||||
NETWORK="\\( ${GREP_REGEXP_NAME}\\)\\?"
|
||||
fi
|
||||
_grep_regexp=" ${INSTANCE_PORT}/${PROTO}${NETWORK}"
|
||||
fi
|
||||
|
||||
local ufw_output
|
||||
ufw_output="$(ufw status numbered)"
|
||||
|
||||
grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\\( ${NETWORK}\\)\$" <<< "$ufw_output" ||
|
||||
grep "# allow ${INSTANCE_NAME}\\( ${INSTANCE_PORT}\\/${PROTO}\\)\$" <<< "$ufw_output" ||
|
||||
grep "# allow ${INSTANCE_NAME}\$" <<< "$ufw_output"
|
||||
grep "# allow ${INSTANCE_NAME}\\(/v6\\)\\?${_grep_regexp}\$" <<< "$ufw_output"
|
||||
}
|
||||
|
||||
function ufw-docker--list-number() {
|
||||
|
@ -155,7 +165,7 @@ function ufw-docker--instance-name() {
|
|||
{
|
||||
{
|
||||
docker inspect --format='{{.Name}}' "$INSTANCE_ID" 2>/dev/null | sed -e 's,^/,,' |
|
||||
grep "^${GREP_REGEXP_INSTANCE_NAME}\$" 2>/dev/null
|
||||
grep "^${GREP_REGEXP_NAME}\$" 2>/dev/null
|
||||
} || echo -n "$INSTANCE_ID";
|
||||
} | remove_blank_lines
|
||||
}
|
||||
|
@ -171,7 +181,7 @@ function ufw-docker--service() {
|
|||
shift || true
|
||||
declare service_id_or_name="${1:?Missing swarm service name or service ID}"
|
||||
|
||||
"ufw-docker--service-${service_action}" "${service_id_or_name}"
|
||||
"ufw-docker--service-${service_action}" "$@"
|
||||
;;
|
||||
allow)
|
||||
shift || true
|
||||
|
@ -221,22 +231,24 @@ function ufw-docker--service-allow() {
|
|||
declare service_id
|
||||
service_id="$(ufw-docker--get-service-id "${service_name}")"
|
||||
[[ -z "${service_id:-}" ]] && die "Could not find service \"$service_name\""
|
||||
|
||||
service_name="$(ufw-docker--get-service-name "${service_name}")"
|
||||
|
||||
declare env_value= published_port= target_port=
|
||||
exec 9< <(ufw-docker--list-service-ports "$service_name")
|
||||
while read -u 9 -r port target_port; do
|
||||
while read -u 9 -r published_port target_port; do
|
||||
if [[ "$target_port" = "${service_port}/${service_proto}" ]]; then
|
||||
declare service_env="ufw_public_${service_id}=${service_name}/${port}/${service_proto}"
|
||||
env_value="${service_name}/${published_port}/${service_proto}"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
exec 9<&-
|
||||
|
||||
[[ -z "${service_env:-}" ]] && die "Service $service_name does not publish port $service_port."
|
||||
[[ -z "${env_value:-}" ]] && die "Service $service_name does not publish port $service_port."
|
||||
|
||||
declare service_env
|
||||
if ! docker service inspect "$ufw_docker_agent" &>/dev/null; then
|
||||
err "Not found ufw-docker-agent service, creating ..."
|
||||
service_env="ufw_public_${service_id}=${env_value}"
|
||||
docker service create --name "$ufw_docker_agent" --mode global \
|
||||
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
|
||||
--mount type=bind,source=/etc/ufw,target=/etc/ufw,readonly=true \
|
||||
|
@ -245,15 +257,20 @@ function ufw-docker--service-allow() {
|
|||
--env "${service_env}" \
|
||||
"${ufw_docker_agent_image}"
|
||||
else
|
||||
declare -a service_env_list
|
||||
service_env_list+=(--env-add "${service_env}")
|
||||
|
||||
declare -a value_list=() service_env_list=()
|
||||
exec 8< <(ufw-docker--get-env-list)
|
||||
while read -u 8 -r id value; do
|
||||
[[ "$id" = "$service_id" ]] && continue
|
||||
[[ "$value" = "${service_name}"/* ]] && service_env_list+=(--env-rm "ufw_public_${id}")
|
||||
[[ "$id" != "$service_id" && "$value" = "${service_name}"/* ]] && service_env_list+=(--env-rm "ufw_public_${id}")
|
||||
[[ "$id" = "$service_id" ]] || continue
|
||||
[[ "${value}" = "${env_value}" || "${value}" = "${env_value}"/* ]] ||
|
||||
value_list+=("${value}")
|
||||
done
|
||||
exec 8<&-
|
||||
value_list=("${env_value}" "${value_list[@]}")
|
||||
|
||||
service_env="ufw_public_${service_id}=$(IFS="${ENV_VALUE_SPLITTER}"; printf '%s' "${value_list[*]}")"
|
||||
|
||||
service_env_list+=(--env-add "${service_env}")
|
||||
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
|
@ -269,24 +286,57 @@ function ufw-docker--get-env-list() {
|
|||
--format '{{range $k,$v := .Spec.TaskTemplate.ContainerSpec.Env}}{{ $v }}{{"\n"}}{{end}}' |
|
||||
sed -e '/^ufw_public_/!d' \
|
||||
-e 's/^ufw_public_//' \
|
||||
-e 's/=/ /'
|
||||
-e 's/=/ /' |
|
||||
while read -r id value; do
|
||||
tr ',' '\n' <<< "$value" | sed "s/^/${id} /g"
|
||||
done
|
||||
}
|
||||
|
||||
function ufw-docker--service-delete() {
|
||||
declare service_name="$1"
|
||||
declare service_port="${2:-}"
|
||||
declare port proto
|
||||
if [[ "${service_port:-}" = */* ]]; then
|
||||
port="${service_port%/*}"
|
||||
proto="${service_port#*/}"
|
||||
elif [[ -n "${service_port:-}" ]]; then
|
||||
port="$service_port"
|
||||
proto="$DEFAULT_PROTO"
|
||||
fi
|
||||
|
||||
declare service_id
|
||||
service_id="$(ufw-docker--get-service-id "${service_name}")"
|
||||
[[ -z "${service_id:-}" ]] && die "Could not find service \"$service_name\""
|
||||
service_name="$(ufw-docker--get-service-name "${service_name}")"
|
||||
|
||||
declare env_value= published_port= target_port=
|
||||
if [[ -n "${port:-}" ]]; then
|
||||
exec 9< <(ufw-docker--list-service-ports "$service_name")
|
||||
while read -u 9 -r published_port target_port; do
|
||||
if [[ "$target_port" = "${port}/${proto}" ]]; then
|
||||
env_value="${service_name}/${published_port}/${proto}"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
exec 9<&-
|
||||
[[ -n "${env_value:-}" ]] || die "Service $service_name does not publish port $service_port."
|
||||
else
|
||||
declare env_value="${service_name}"
|
||||
fi
|
||||
|
||||
declare id value
|
||||
declare -a value_list=()
|
||||
exec 8< <(ufw-docker--get-env-list)
|
||||
while read -u 8 -r id value; do
|
||||
if [[ "$id" = "$service_name" ]] || [[ "$value" = "${service_name}"/* ]]; then
|
||||
declare service_id="$id"
|
||||
service_name="${value%%/*}"
|
||||
declare service_env="ufw_public_${service_id}=${service_name}/deny"
|
||||
break;
|
||||
fi
|
||||
[[ "$id" = "$service_id" ]] || continue
|
||||
[[ "${value}" = "${env_value}" || "${value}" = "${env_value}"/* ]] ||
|
||||
value_list+=("${value}")
|
||||
done
|
||||
exec 8<&-
|
||||
value_list=("${env_value}/deny" "${value_list[@]}")
|
||||
|
||||
[[ -z "${service_env:-}" ]] && die "Could not find service \"$service_name\""
|
||||
declare service_env
|
||||
service_env="ufw_public_${service_id}=$(IFS="${ENV_VALUE_SPLITTER}"; printf '%s' "${value_list[*]}")"
|
||||
|
||||
docker service update --update-parallelism=0 \
|
||||
--env-add ufw_docker_agent_image="${ufw_docker_agent_image}" \
|
||||
|
@ -300,9 +350,6 @@ function ufw-docker--raw-command() {
|
|||
ufw "$@"
|
||||
}
|
||||
|
||||
after_rules="/etc/ufw/after.rules"
|
||||
after6_rules="/etc/ufw/after6.rules"
|
||||
|
||||
function ufw-docker--check() {
|
||||
err "\\n########## iptables -n -L DOCKER-USER ##########"
|
||||
iptables -n -L DOCKER-USER
|
||||
|
@ -370,7 +417,7 @@ function ufw-docker--check-install() {
|
|||
after_rules_tmp="${after_rules_tmp:-$(mktemp)}"
|
||||
rm-on-exit "$after_rules_tmp"
|
||||
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" > "$after_rules_tmp"
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after_rules" | tee "$after_rules_tmp" >/dev/null
|
||||
{
|
||||
cat <<-\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
|
@ -409,7 +456,7 @@ function ufw-docker--check-install() {
|
|||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
} >> "${after_rules_tmp}"
|
||||
} | tee -a "${after_rules_tmp}" >/dev/null
|
||||
diff -u --color=auto "$after_rules" "$after_rules_tmp"
|
||||
}
|
||||
|
||||
|
@ -430,7 +477,7 @@ function ufw-docker--check-install_ipv6() {
|
|||
after6_rules_tmp="${after6_rules_tmp:-$(mktemp)}"
|
||||
rm-on-exit "$after6_rules_tmp"
|
||||
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after6_rules" > "$after6_rules_tmp"
|
||||
sed "/^# BEGIN UFW AND DOCKER/,/^# END UFW AND DOCKER/d" "$after6_rules" | tee "$after6_rules_tmp" >/dev/null
|
||||
{
|
||||
cat <<-\EOF
|
||||
# BEGIN UFW AND DOCKER
|
||||
|
@ -465,7 +512,7 @@ function ufw-docker--check-install_ipv6() {
|
|||
COMMIT
|
||||
# END UFW AND DOCKER
|
||||
EOF
|
||||
} >> "${after6_rules_tmp}"
|
||||
} | tee -a "${after6_rules_tmp}"
|
||||
diff -u --color=auto "$after6_rules" "$after6_rules_tmp"
|
||||
}
|
||||
|
||||
|
@ -624,7 +671,7 @@ case "$ufw_action" in
|
|||
INSTANCE_PORT="${INSTANCE_PORT%/*}"
|
||||
;;&
|
||||
delete|list)
|
||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME\\(/v6\\)\\?" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||
;;
|
||||
allow)
|
||||
"ufw-docker--$ufw_action" "$INSTANCE_NAME" "$INSTANCE_PORT" "$PROTO" "$NETWORK"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue