ci / validate (push) Skipped
ci / lint-prettier (push) Skipped
ci / lint-ruff (push) Skipped
ci / lint-yaml (push) Skipped
ci / lint-dockerfiles (push) Skipped
renovate-ci / validate-renovate (push) Skipped
renovate-ci / validate-renovate (pull_request) Skipped
ci / lint-compose (pull_request) Successful in 12s
ci / lint-actionlint (pull_request) Successful in 8s
ci / lint-shellcheck (pull_request) Successful in 21s
ci / lint-prettier (pull_request) Successful in 17s
ci / lint-ruff (pull_request) Successful in 6s
ci / lint-yaml (pull_request) Successful in 9s
ci / lint-dockerfiles (pull_request) Successful in 5s
ci / validate (pull_request) Successful in 6s
ci / build (pull_request) Skipped
88 lines
3.7 KiB
Python
88 lines
3.7 KiB
Python
"""Exercise local setup and config rendering without a Docker daemon."""
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
class NetbirdRuntimeTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.temp.cleanup)
|
|
self.root = Path(self.temp.name)
|
|
self.stack = self.root / 'netbird'
|
|
self.stack.mkdir()
|
|
for name in ('setup.sh', '.env.example', 'config.template.yaml'):
|
|
shutil.copy(ROOT / 'netbird' / name, self.stack / name)
|
|
binary = self.root / 'bin'
|
|
binary.mkdir()
|
|
docker = binary / 'docker'
|
|
docker.write_text('#!/bin/sh\nprintf "%s\\n" 172.20.0.0/16\n')
|
|
docker.chmod(0o755)
|
|
self.env = dict(os.environ, PATH=f'{binary}:{os.environ["PATH"]}')
|
|
|
|
def setup(self):
|
|
return subprocess.run( # noqa: S603 - executes the repository script copied into this test's temp dir
|
|
['/bin/bash', str(self.stack / 'setup.sh')], env=self.env, capture_output=True, check=False
|
|
)
|
|
|
|
def test_setup_preserves_existing_secrets_and_env(self):
|
|
self.assertEqual(self.setup().returncode, 0)
|
|
paths = [self.stack / '.env', *sorted((self.stack / 'secrets').iterdir())]
|
|
before = [p.read_bytes() for p in paths]
|
|
self.assertIn(b'NETBIRD_PROXY_SUBNET=172.20.0.0/16', before[0])
|
|
self.assertEqual(self.setup().returncode, 0)
|
|
self.assertEqual(before, [p.read_bytes() for p in paths])
|
|
for p in paths[1:]:
|
|
self.assertEqual(p.stat().st_mode & 0o777, 0o600)
|
|
|
|
def test_setup_rejects_empty_existing_secret(self):
|
|
(self.stack / 'secrets').mkdir()
|
|
secret = self.stack / 'secrets/datastore-encryption-key'
|
|
secret.touch()
|
|
self.assertNotEqual(self.setup().returncode, 0)
|
|
self.assertEqual(secret.read_bytes(), b'')
|
|
|
|
def render(self, subnet):
|
|
self.assertEqual(self.setup().returncode, 0)
|
|
rendered = self.root / 'run/config.yaml'
|
|
script = (ROOT / 'netbird/entrypoint.sh').read_text()
|
|
replacements = {
|
|
'/opt/netbird/config.template.yaml': str(self.stack / 'config.template.yaml'),
|
|
'/run/netbird/config.yaml': str(rendered),
|
|
'/run/secrets/relay_auth_secret': str(self.stack / 'secrets/relay-auth-secret'),
|
|
'/run/secrets/datastore_encryption_key': str(self.stack / 'secrets/datastore-encryption-key'),
|
|
'/go/bin/netbird-server': '/bin/true',
|
|
}
|
|
for original, local in replacements.items():
|
|
script = script.replace(original, local)
|
|
result = subprocess.run( # noqa: S603 - repository renderer, with test-local paths
|
|
['/bin/sh', '-c', script, 'entrypoint', '--config', str(rendered)],
|
|
env=dict(self.env, NETBIRD_DOMAIN='nb.example.com', NETBIRD_PROXY_SUBNET=subnet),
|
|
capture_output=True,
|
|
check=False,
|
|
)
|
|
return result, rendered
|
|
|
|
def test_renderer_replaces_placeholders_and_restricts_file_permissions(self):
|
|
result, rendered = self.render('172.20.0.0/16')
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertNotIn('__NETBIRD_', rendered.read_text())
|
|
self.assertIn('nb.example.com', rendered.read_text())
|
|
self.assertEqual(rendered.stat().st_mode & 0o777, 0o600)
|
|
|
|
def test_renderer_rejects_auto_and_default_route(self):
|
|
for subnet in ('auto', '0.0.0.0/0', '999.1.1.1/24'):
|
|
with self.subTest(subnet=subnet):
|
|
result, _ = self.render(subnet)
|
|
self.assertNotEqual(result.returncode, 0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|