From 7c3c1cabf5a4b830af5ea37dcd8c0ed29ee5e921 Mon Sep 17 00:00:00 2001 From: mwiegand Date: Sun, 10 Oct 2021 01:18:05 +0200 Subject: [PATCH] wip --- bin/wireguard_client_config | 3 +- bundles/wireguard/metadata.py | 137 ++++++++++++++++++---------------- libs/keys.py | 15 ---- libs/wireguard.py | 23 +++--- 4 files changed, 83 insertions(+), 95 deletions(-) delete mode 100644 libs/keys.py diff --git a/bin/wireguard_client_config b/bin/wireguard_client_config index 1dfd7d8..6afd113 100755 --- a/bin/wireguard_client_config +++ b/bin/wireguard_client_config @@ -8,13 +8,12 @@ from ipaddress import ip_network, ip_interface repo = Repository(dirname(dirname(realpath(__file__)))) server_node = repo.get_node('htz.mails') -server_pubkey = repo.libs.keys.get_pubkey_from_privkey(f'{server_node.name} wireguard pubkey', server_node.metadata.get('wireguard/privatekey')) +server_pubkey = repo.libs.wireguard.pubkey(server_node.metadata.get('id')) data = server_node.metadata.get(f'wireguard/clients/{argv[1]}') sortable_client_routes = [ ip_interface(server_node.metadata.get('network/internal/ipv4')).network, ] - for peer in server_node.metadata.get('wireguard/peers').values(): for network in peer.get('route'): sortable_client_routes.append(ip_network(network)) diff --git a/bundles/wireguard/metadata.py b/bundles/wireguard/metadata.py index 4ec3618..8ea0f9f 100644 --- a/bundles/wireguard/metadata.py +++ b/bundles/wireguard/metadata.py @@ -3,6 +3,7 @@ from ipaddress import ip_network, ip_interface from bundlewrap.exceptions import NoSuchNode from bundlewrap.metadata import atomic +repo.libs.wireguard.repo = repo defaults = { 'apt': { @@ -19,12 +20,79 @@ defaults = { }, }, }, - 'wireguard': { - 'privatekey': repo.vault.random_bytes_as_base64_for(f'{node.name} wireguard privatekey'), - }, } +@metadata_reactor.provides( + 'wireguard/privkey', +) +def privkey(metadata): + return { + 'wireguard': { + 'privkey': repo.libs.wireguard.privkey(metadata.get('id')), + } + } + + +@metadata_reactor.provides( + 'wireguard/peers', +) +def s2s_peer_specific(metadata): + return { + 'wireguard': { + 'peers': { + peer: { + 'id': repo.get_node(peer).metadata.get(f'id'), + 'privkey': repo.get_node(peer).metadata.get(f'wireguard/privkey'), + 'ip': repo.get_node(peer).metadata.get(f'wireguard/my_ip'), + 'endpoint': f'{repo.get_node(peer).hostname}:51820', + + } + for peer in metadata.get('wireguard/peers') + }, + }, + } + + +@metadata_reactor.provides( + 'wireguard/clients', +) +def client_peer_specific(metadata): + return { + 'wireguard': { + 'clients': { + client: { + 'id': client, + 'privkey': repo.libs.wireguard.privkey(client), + } + for client in metadata.get('wireguard/clients') + }, + }, + } + + +@metadata_reactor.provides( + 'wireguard/peers', + 'wireguard/clients', +) +def common_peer_data(metadata): + peers = { + 'peers': {}, + 'clients': {}, + } + + for peer_type in peers: + for peer_name, peer_data in metadata.get(f'wireguard/{peer_type}', {}).items(): + peers[peer_type][peer_name] = { + 'psk': repo.libs.wireguard.psk(node.metadata.get('id'), peer_data['id']), + 'pubkey': repo.libs.wireguard.pubkey(peer_data['id']), + } + + return { + 'wireguard': peers, + } + + @metadata_reactor.provides( 'systemd/units', ) @@ -82,7 +150,7 @@ def systemd_networkd_netdevs(metadata): 'Description': 'WireGuard server', }, 'WireGuard': { - 'PrivateKey': metadata.get('wireguard/privatekey'), + 'PrivateKey': metadata.get('wireguard/privkey'), 'ListenPort': 51820, }, } @@ -112,64 +180,3 @@ def systemd_networkd_netdevs(metadata): }, }, } - - -@metadata_reactor.provides( - 'wireguard/peers', -) -def s2s_peer_specific(metadata): - return { - 'wireguard': { - 'peers': { - peer: { - 'id': repo.get_node(peer).metadata.get(f'id'), - 'privkey': repo.get_node(peer).metadata.get(f'wireguard/privatekey'), - 'ip': repo.get_node(peer).metadata.get(f'wireguard/my_ip'), - 'endpoint': f'{repo.get_node(peer).hostname}:51820', - - } - for peer in metadata.get('wireguard/peers') - }, - }, - } - - -@metadata_reactor.provides( - 'wireguard/clients', -) -def client_peer_specific(metadata): - return { - 'wireguard': { - 'clients': { - client: { - 'id': client, - 'privkey': repo.vault.random_bytes_as_base64_for(f'{client} wireguard privatekey'), - } - for client in metadata.get('wireguard/clients') - }, - }, - } - - -@metadata_reactor.provides( - 'wireguard/peers', - 'wireguard/clients', -) -def common_peer_data(metadata): - peers = { - 'peers': {}, - 'clients': {}, - } - - for peer_type in peers: - for peer_name, peer_data in metadata.get(f'wireguard/{peer_type}', {}).items(): - first, second = sorted([node.metadata.get('id'), peer_data['id']]) - - peers[peer_type][peer_name] = { - 'psk': repo.vault.random_bytes_as_base64_for(f'{first} wireguard {second}'), - 'pubkey': repo.libs.keys.get_pubkey_from_privkey(f'{peer_name} wireguard pubkey', peer_data['privkey']), - } - - return { - 'wireguard': peers, - } diff --git a/libs/keys.py b/libs/keys.py deleted file mode 100644 index 427a85f..0000000 --- a/libs/keys.py +++ /dev/null @@ -1,15 +0,0 @@ -import base64 -from nacl.public import PrivateKey -from nacl.encoding import Base64Encoder -from bundlewrap.utils import Fault - -def gen_privkey(repo, identifier): - return repo.vault.random_bytes_as_base64_for(identifier) - -def get_pubkey_from_privkey(identifier, privkey): - # FIXME this assumes the privkey is always a base64 encoded string - def derive_pubkey(): - pub_key = PrivateKey(base64.b64decode(str(privkey))).public_key - return pub_key.encode(encoder=Base64Encoder).decode('ascii') - - return Fault(f'pubkey from privkey {identifier}', derive_pubkey) diff --git a/libs/wireguard.py b/libs/wireguard.py index 91704e8..9f63e61 100644 --- a/libs/wireguard.py +++ b/libs/wireguard.py @@ -1,15 +1,12 @@ -connections = {} +import base64 +from nacl.public import PrivateKey +from nacl.encoding import Base64Encoder -def get_connection(node, other_node): - global connections - - node_id, other_node_id = node.metadata.get('id'), other_node.metadata.get('id') - sorted_ids = tuple(sorted([node_id, other_node_id])) - - if sorted_ids not in connections: - connections[sorted_ids] = { - 'pubkey': node.repo.libs.keys.get_pubkey_from_privkey(f'{other_node_id} wireguard pubkey', other_node.metadata.get('wireguard/privatekey')), - 'psk': node.repo.vault.random_bytes_as_base64_for(f"{sorted_ids[0]} wireguard {sorted_ids[1]}"), - } +def privkey(id): + return str(repo.vault.random_bytes_as_base64_for(f"wireguard privkey {id}")) - return connections[sorted_ids] +def pubkey(id): + return PrivateKey(base64.b64decode(privkey(id))).public_key.encode(encoder=Base64Encoder).decode('ascii') + +def psk(id1, id2): + return repo.vault.random_bytes_as_base64_for(f"wireguard psk {' '.join(sorted([id1, id2]))}")