This commit is contained in:
mwiegand 2021-10-10 01:18:05 +02:00
parent ce7b3a0fc7
commit 7c3c1cabf5
4 changed files with 83 additions and 95 deletions

View file

@ -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))

View file

@ -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,
}

View file

@ -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)

View file

@ -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]))}")