1
0
mirror of https://github.com/Tecnativa/docker-socket-proxy synced 2025-01-03 04:10:55 +00:00

Add first version of tests

From https://github.com/Tecnativa/docker-socket-proxy/pull/14
This commit is contained in:
João Marques 2020-10-29 12:25:56 +00:00
parent a07d4ae4d9
commit 0a0b6f8f12
4 changed files with 367 additions and 0 deletions

177
poetry.lock generated Normal file
View File

@ -0,0 +1,177 @@
[[package]]
name = "atomicwrites"
version = "1.4.0"
description = "Atomic file writes."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "attrs"
version = "20.3.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.extras]
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"]
docs = ["furo", "sphinx", "zope.interface"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
[[package]]
name = "colorama"
version = "0.4.4"
description = "Cross-platform colored terminal text."
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "iniconfig"
version = "1.1.1"
description = "iniconfig: brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "packaging"
version = "20.4"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.dependencies]
pyparsing = ">=2.0.2"
six = "*"
[[package]]
name = "pluggy"
version = "0.13.1"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.extras]
dev = ["pre-commit", "tox"]
[[package]]
name = "plumbum"
version = "1.6.9"
description = "Plumbum: shell combinators library"
category = "main"
optional = false
python-versions = ">=2.6,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
[[package]]
name = "py"
version = "1.9.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pyparsing"
version = "2.4.7"
description = "Python parsing module"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "pytest"
version = "6.1.2"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.5"
[package.dependencies]
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
attrs = ">=17.4.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<1.0"
py = ">=1.8.2"
toml = "*"
[package.extras]
checkqa_mypy = ["mypy (==0.780)"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
name = "six"
version = "1.15.0"
description = "Python 2 and 3 compatibility utilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "aad93df5d769d433d8739fc1fb317b1d53d9e8ddd18efaaaf8a864d543734c5a"
[metadata.files]
atomicwrites = [
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
]
attrs = [
{file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"},
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"},
]
colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
]
packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
]
plumbum = [
{file = "plumbum-1.6.9-py2.py3-none-any.whl", hash = "sha256:91418dcc66b58ab9d2e3b04b3d1e0d787dc45923154fb8b4a826bd9316dba0d6"},
{file = "plumbum-1.6.9.tar.gz", hash = "sha256:16b9e19d96c80f2e9d051ef5f04927b834a6ac0ce5d2768eb8662b5cd53e43df"},
]
py = [
{file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
{file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
]
pytest = [
{file = "pytest-6.1.2-py3-none-any.whl", hash = "sha256:4288fed0d9153d9646bfcdf0c0428197dba1ecb27a33bb6e031d002fa88653fe"},
{file = "pytest-6.1.2.tar.gz", hash = "sha256:c0a7e94a8cdbc5422a51ccdad8e6f1024795939cc89159a0ae7f0b316ad3823e"},
]
six = [
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
]
toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]

16
pyproject.toml Normal file
View File

@ -0,0 +1,16 @@
[tool.poetry]
name = "docker-socket-proxy"
version = "0.1.0"
description = ""
authors = ["Tecnativa S.L"]
[tool.poetry.dependencies]
python = "^3.8"
plumbum = "^1.6.9"
[tool.poetry.dev-dependencies]
pytest = "^6.1.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

84
tests/run_tests.sh Executable file
View File

@ -0,0 +1,84 @@
#!/bin/bash
set -eu
proxy_container=docksockprox_test
socket_proxy=127.0.0.1:2375
start_proxy() {
echo "Starting $proxy_container with args: ${*}..."
docker run -d --name "$proxy_container" \
-v /var/run/docker.sock:/var/run/docker.sock \
-p "${socket_proxy}:2375" \
"$@" \
tecnativa/docker-socket-proxy &>/dev/null
}
delete_proxy() {
echo "Removing ${proxy_container}..."
docker rm -f "$proxy_container" &>/dev/null
}
docker_with_proxy() {
docker --host "$socket_proxy" "$@" 2>&1
}
assert() {
assertion=$1
shift 1
if docker_with_proxy "$@" | grep -qi 'forbidden'; then
result='forbidden'
else
result='allowed'
fi
if [ "$assertion" == "$result" ]; then
printf '%s' 'PASS'
else
printf '%s' 'FAIL'
fi
echo " | assert 'docker $*' is $assertion"
}
trap delete_proxy EXIT
start_proxy
assert allowed version
assert forbidden run --rm alpine
assert forbidden pull alpine
assert forbidden logs "$proxy_container"
assert forbidden wait "$proxy_container"
assert forbidden rm -f "$proxy_container"
assert forbidden restart "$proxy_container"
assert forbidden network ls
assert forbidden config ls
assert forbidden service ls
assert forbidden stack ls
assert forbidden secret ls
assert forbidden plugin ls
assert forbidden info
assert forbidden system info
assert forbidden build .
assert forbidden swarm init
delete_proxy
start_proxy -e CONTAINERS=1
assert allowed logs "$proxy_container"
assert allowed inspect "$proxy_container"
assert forbidden wait "$proxy_container"
assert forbidden run --rm alpine
assert forbidden rm -f "$proxy_container"
assert forbidden restart "$proxy_container"
delete_proxy
start_proxy -e POST=1
assert forbidden rm -f "$proxy_container"
assert forbidden pull alpine
assert forbidden run --rm alpine
assert forbidden network create foobar
delete_proxy
start_proxy -e NETWORKS=1 -e POST=1
assert allowed network ls
assert allowed network create foo
assert allowed network rm foo

90
tests/test_service.py Normal file
View File

@ -0,0 +1,90 @@
import pytest
import logging
from plumbum import ProcessExecutionError, local
from plumbum.cmd import docker
from plumbum.machines.local import LocalCommand
logger = logging.getLogger()
CONTAINER_NAME = "docksockprox_test"
SOCKET_PROXY = "127.0.0.1:2375"
def _start_proxy(
container_name=CONTAINER_NAME,
socket_proxy=SOCKET_PROXY,
extra_args=None
):
logger.info(f"Starting {container_name} with args: {extra_args}...")
docker(
"run",
"-d",
"--name", container_name,
"--privileged",
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"-p", f"{socket_proxy}:2375",
extra_args,
"tecnativa/docker-socket-proxy",
)
def _stop_and_delete_proxy(
container_name=CONTAINER_NAME,
socket_proxy=SOCKET_PROXY,
):
logger.info(f"Removing {container_name}...")
docker(
"rm",
"-f",
container_name,
)
def _query_docker_with_proxy(socket_proxy=SOCKET_PROXY, extra_args=None):
try:
_ret_code, stdout, stderr = docker.run(
(
"--host",
socket_proxy,
extra_args,
)
)
except ProcessExecutionError as result:
stdout = result.stdout
stderr = result.stderr
return stdout + stderr
def _check_permission(assertion, extra_args=None):
if "forbidden" in _query_docker_with_proxy(extra_args=extra_args):
result = "forbidden"
else:
result = "allowed"
assert result == assertion
def test_default_permissions():
try:
_start_proxy()
_check_permission("allowed", extra_args="version")
_check_permission("forbidden", ["run", "--rm", "alpine"])
_check_permission("forbidden", ["pull", "alpine"])
_check_permission("forbidden", ["logs", CONTAINER_NAME])
_check_permission("forbidden", ["wait", CONTAINER_NAME])
_check_permission("forbidden", ["rm", "-f", CONTAINER_NAME])
_check_permission("forbidden", ["restart", CONTAINER_NAME])
_check_permission("forbidden", ["network", "ls"])
_check_permission("forbidden", ["config", "ls"])
_check_permission("forbidden", ["service", "ls"])
_check_permission("forbidden", ["stack", "ls"])
_check_permission("forbidden", ["secret", "ls"])
_check_permission("forbidden", ["plugin", "ls"])
_check_permission("forbidden", ["info"])
_check_permission("forbidden", ["system", "info"])
_check_permission("forbidden", ["build", "."])
_check_permission("forbidden", ["swarm", "init"])
finally:
pass
_stop_and_delete_proxy()