From 35071d2b6fc643fde9e383deeffb6455d91ca93e Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Fri, 27 Dec 2024 23:53:58 +0300 Subject: [PATCH 1/6] add static peer formatting for client config --- tests/test_app.py | 9 ++++++--- vpn_manager/__init__.py | 2 ++ vpn_manager/__main__.py | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tests/test_app.py b/tests/test_app.py index 725f245..b089239 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,3 +1,6 @@ -def test_true(): - assert True - \ No newline at end of file +from vpn_manager import * + +def test_format_static_peer(): + sp = StaticPeer('sample-public-key', '127.0.0.1', '12345') + peer_section = format_static_peer(sp, '0.0.0.0/0') + assert peer_section == '[Peer]\nPublicKey = sample-public-key\nAllowedIPs = 0.0.0.0/0\nEndpoint = 127.0.0.1:12345\nPersistentKeepAlive = 30' diff --git a/vpn_manager/__init__.py b/vpn_manager/__init__.py index e69de29..737754e 100644 --- a/vpn_manager/__init__.py +++ b/vpn_manager/__init__.py @@ -0,0 +1,2 @@ +from .__main__ import * + diff --git a/vpn_manager/__main__.py b/vpn_manager/__main__.py index 31564bb..46b7f94 100644 --- a/vpn_manager/__main__.py +++ b/vpn_manager/__main__.py @@ -1,3 +1,21 @@ +from dataclasses import dataclass + +@dataclass +class StaticPeer: + public_key: str + endpoint: str + port: str + + +def format_static_peer(static_peer, routes, keepalive=30): + return f'''[Peer] +PublicKey = {static_peer.public_key} +AllowedIPs = {routes} +Endpoint = {static_peer.endpoint}:{static_peer.port} +PersistentKeepAlive = {keepalive}''' + + + def main(): print("run") -- 2.54.0 From 8907ed33f86c59aa8a1b161f7a351d22891890bb Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Sat, 28 Dec 2024 01:09:24 +0300 Subject: [PATCH 2/6] add interface section formatting --- .activate | 7 +++++++ tests/test_app.py | 15 ++++++++++++-- vpn_manager/__init__.py | 1 - vpn_manager/__main__.py | 46 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 .activate diff --git a/.activate b/.activate new file mode 100644 index 0000000..a3607ff --- /dev/null +++ b/.activate @@ -0,0 +1,7 @@ + +alias venv='source .venv/Scripts/activate' +alias check='flake8 vpn_manager' +alias format='black vpn_manager' +alias test='pytest' + +venv diff --git a/tests/test_app.py b/tests/test_app.py index b089239..6e7523d 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,6 +1,17 @@ from vpn_manager import * def test_format_static_peer(): - sp = StaticPeer('sample-public-key', '127.0.0.1', '12345') + sp = Peer('PUB', "PRV", '10.0.0.1/32', '12345', '127.0.0.1') peer_section = format_static_peer(sp, '0.0.0.0/0') - assert peer_section == '[Peer]\nPublicKey = sample-public-key\nAllowedIPs = 0.0.0.0/0\nEndpoint = 127.0.0.1:12345\nPersistentKeepAlive = 30' + assert peer_section == '[Peer]\nPublicKey = PUB\nAllowedIPs = 0.0.0.0/0\nEndpoint = 127.0.0.1:12345\nPersistentKeepAlive = 30' + + +def test_true(): + assert format_interface(Peer('PUB', 'PRV', '10.0.0.1/32', 'PORT'), '1.1.1.1') \ + == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nListenPort = PORT\nDNS = 1.1.1.1' + assert format_interface(Peer('PUB', 'PRV', '10.0.0.1/32', None), '1.1.1.1') \ + == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nDNS = 1.1.1.1' + assert format_interface(Peer('PUB', 'PRV', '10.0.0.1/32', 'PORT'), '1.1.1.1', forward=True) \ + == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nListenPort = PORT\nDNS = 1.1.1.1\nPostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nPostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE' + assert format_interface(Peer('PUB', 'PRV', '10.0.0.1/32', None), '1.1.1.1', forward=True) \ + == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nDNS = 1.1.1.1\nPostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nPostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE' diff --git a/vpn_manager/__init__.py b/vpn_manager/__init__.py index 737754e..a86c6bb 100644 --- a/vpn_manager/__init__.py +++ b/vpn_manager/__init__.py @@ -1,2 +1 @@ from .__main__ import * - diff --git a/vpn_manager/__main__.py b/vpn_manager/__main__.py index 46b7f94..9470d5b 100644 --- a/vpn_manager/__main__.py +++ b/vpn_manager/__main__.py @@ -1,19 +1,55 @@ from dataclasses import dataclass +from textwrap import dedent + @dataclass -class StaticPeer: +class Peer: public_key: str - endpoint: str + private_key: str + address_cidr: str port: str + endpoint: str = None def format_static_peer(static_peer, routes, keepalive=30): - return f'''[Peer] + return f""" +[Peer] PublicKey = {static_peer.public_key} AllowedIPs = {routes} Endpoint = {static_peer.endpoint}:{static_peer.port} -PersistentKeepAlive = {keepalive}''' - +PersistentKeepAlive = {keepalive} +""".strip() + + +def format_interface(peer, dns, forward=False): + if forward: + forward = dedent( + """\ + PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + """ + ) + # wg0 always? + # eth0 always? + else: + forward = "" + if peer.port: + port = f"ListenPort = {peer.port}\n" + else: + port = "" + dns = f"DNS = {dns}\n" + return f""" +[Interface] +PrivateKey = {peer.private_key} +Address = {peer.address_cidr} +{port}\ +{dns}\ +{forward}\ +""".strip() + + +def remove_empty_lines(text): + return "\n".join([s for s in text.splitlines() if s.strip()]) def main(): -- 2.54.0 From 02a4f590f2aa3515dc33b4a6a3b8773b34fa34df Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Sat, 28 Dec 2024 18:50:30 +0300 Subject: [PATCH 3/6] work around relative imports --- tests/test_app.py | 3 ++- vpn_manager/__init__.py | 4 ++- vpn_manager/__main__.py | 54 ----------------------------------------- vpn_manager/peers.py | 48 ++++++++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 56 deletions(-) create mode 100644 vpn_manager/peers.py diff --git a/tests/test_app.py b/tests/test_app.py index 6e7523d..4918262 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,4 +1,4 @@ -from vpn_manager import * +from vpn_manager.peers import * def test_format_static_peer(): sp = Peer('PUB', "PRV", '10.0.0.1/32', '12345', '127.0.0.1') @@ -15,3 +15,4 @@ def test_true(): == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nListenPort = PORT\nDNS = 1.1.1.1\nPostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nPostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE' assert format_interface(Peer('PUB', 'PRV', '10.0.0.1/32', None), '1.1.1.1', forward=True) \ == '[Interface]\nPrivateKey = PRV\nAddress = 10.0.0.1/32\nDNS = 1.1.1.1\nPostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\nPostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE' + diff --git a/vpn_manager/__init__.py b/vpn_manager/__init__.py index a86c6bb..a03af42 100644 --- a/vpn_manager/__init__.py +++ b/vpn_manager/__init__.py @@ -1 +1,3 @@ -from .__main__ import * +from . import peers + +__all__ = ["peers"] diff --git a/vpn_manager/__main__.py b/vpn_manager/__main__.py index 9470d5b..31564bb 100644 --- a/vpn_manager/__main__.py +++ b/vpn_manager/__main__.py @@ -1,57 +1,3 @@ -from dataclasses import dataclass -from textwrap import dedent - - -@dataclass -class Peer: - public_key: str - private_key: str - address_cidr: str - port: str - endpoint: str = None - - -def format_static_peer(static_peer, routes, keepalive=30): - return f""" -[Peer] -PublicKey = {static_peer.public_key} -AllowedIPs = {routes} -Endpoint = {static_peer.endpoint}:{static_peer.port} -PersistentKeepAlive = {keepalive} -""".strip() - - -def format_interface(peer, dns, forward=False): - if forward: - forward = dedent( - """\ - PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE - PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE - """ - ) - # wg0 always? - # eth0 always? - else: - forward = "" - if peer.port: - port = f"ListenPort = {peer.port}\n" - else: - port = "" - dns = f"DNS = {dns}\n" - return f""" -[Interface] -PrivateKey = {peer.private_key} -Address = {peer.address_cidr} -{port}\ -{dns}\ -{forward}\ -""".strip() - - -def remove_empty_lines(text): - return "\n".join([s for s in text.splitlines() if s.strip()]) - - def main(): print("run") diff --git a/vpn_manager/peers.py b/vpn_manager/peers.py new file mode 100644 index 0000000..06d6302 --- /dev/null +++ b/vpn_manager/peers.py @@ -0,0 +1,48 @@ +from dataclasses import dataclass +from textwrap import dedent + + +@dataclass +class Peer: + public_key: str + private_key: str + address_cidr: str + port: str + endpoint: str = None + + +def format_static_peer(static_peer, routes, keepalive=30): + return f""" +[Peer] +PublicKey = {static_peer.public_key} +AllowedIPs = {routes} +Endpoint = {static_peer.endpoint}:{static_peer.port} +PersistentKeepAlive = {keepalive} +""".strip() + + +def format_interface(peer, dns, forward=False): + if forward: + forward = dedent( + """\ + PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE + """ + ) + # wg0 always? + # eth0 always? + else: + forward = "" + if peer.port: + port = f"ListenPort = {peer.port}\n" + else: + port = "" + dns = f"DNS = {dns}\n" + return f""" +[Interface] +PrivateKey = {peer.private_key} +Address = {peer.address_cidr} +{port}\ +{dns}\ +{forward}\ +""".strip() -- 2.54.0 From 9e3f16175a57b9f62e7b55e6f1e8e0f4cfc1bfaa Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Sat, 28 Dec 2024 19:17:03 +0300 Subject: [PATCH 4/6] add support for pyproject.toml to flake8 --- pyproject.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 3552b50..7f0a731 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,8 +21,12 @@ authors = [ test = ["pytest"] lint = [ "black", - "flake8" + "flake8", + "Flake8-pyproject" ] [project.scripts] example = "vpn_manager.__main__:main" + +[tool.flake8] +ignore = ["E501"] -- 2.54.0 From 1b37f1b57d207b8cec3463fe71e1947f6e50cce6 Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Sat, 28 Dec 2024 19:35:37 +0300 Subject: [PATCH 5/6] neatest way to write multiline f-strings (not fast though) --- vpn_manager/peers.py | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/vpn_manager/peers.py b/vpn_manager/peers.py index 06d6302..929d559 100644 --- a/vpn_manager/peers.py +++ b/vpn_manager/peers.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -from textwrap import dedent @dataclass @@ -12,22 +11,20 @@ class Peer: def format_static_peer(static_peer, routes, keepalive=30): - return f""" -[Peer] -PublicKey = {static_peer.public_key} -AllowedIPs = {routes} -Endpoint = {static_peer.endpoint}:{static_peer.port} -PersistentKeepAlive = {keepalive} -""".strip() + return ( + "[Peer]\n" + f"PublicKey = {static_peer.public_key}\n" + f"AllowedIPs = {routes}\n" + f"Endpoint = {static_peer.endpoint}:{static_peer.port}\n" + f"PersistentKeepAlive = {keepalive}\n" + ).strip() def format_interface(peer, dns, forward=False): if forward: - forward = dedent( - """\ - PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE - PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE - """ + forward = ( + "PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\n" + "PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE\n" ) # wg0 always? # eth0 always? @@ -38,11 +35,11 @@ def format_interface(peer, dns, forward=False): else: port = "" dns = f"DNS = {dns}\n" - return f""" -[Interface] -PrivateKey = {peer.private_key} -Address = {peer.address_cidr} -{port}\ -{dns}\ -{forward}\ -""".strip() + return ( + "[Interface]\n" + f"PrivateKey = {peer.private_key}\n" + f"Address = {peer.address_cidr}\n" + f"{port}" + f"{dns}" + f"{forward}" + ).strip() -- 2.54.0 From 795e22c043ffd70df6ac8b580544fe30c2662860 Mon Sep 17 00:00:00 2001 From: Fedor Lyanguzov Date: Thu, 9 Jan 2025 17:38:11 +0300 Subject: [PATCH 6/6] Add little type annotations --- vpn_manager/peers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpn_manager/peers.py b/vpn_manager/peers.py index 929d559..cfd2d9c 100644 --- a/vpn_manager/peers.py +++ b/vpn_manager/peers.py @@ -10,7 +10,7 @@ class Peer: endpoint: str = None -def format_static_peer(static_peer, routes, keepalive=30): +def format_static_peer(static_peer: Peer, routes, keepalive=30): return ( "[Peer]\n" f"PublicKey = {static_peer.public_key}\n" @@ -20,7 +20,7 @@ def format_static_peer(static_peer, routes, keepalive=30): ).strip() -def format_interface(peer, dns, forward=False): +def format_interface(peer: Peer, dns, forward=False): if forward: forward = ( "PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\n" -- 2.54.0