diff options
| author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-12-10 01:06:58 -0800 |
|---|---|---|
| committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2025-12-10 01:06:58 -0800 |
| commit | 2157a8d75726c9d28a62c298df279e4ed917f16f (patch) | |
| tree | 5f8016ef24fd0ab2782e2555f1f46a0e063e86cc | |
| parent | af89e59722d7bb0df8f84828e007e225ce0aaafd (diff) | |
| download | wg-genconf-2157a8d75726c9d28a62c298df279e4ed917f16f.tar.gz wg-genconf-2157a8d75726c9d28a62c298df279e4ed917f16f.tar.xz | |
support templated interface name and privkey path
| -rwxr-xr-x | wg-genconf.py | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/wg-genconf.py b/wg-genconf.py index adc81e9..3a8269b 100755 --- a/wg-genconf.py +++ b/wg-genconf.py @@ -8,8 +8,8 @@ import functools import io import ipaddress import os -import pathlib import re +import string import shutil import sys import tomllib @@ -55,8 +55,9 @@ class Interface(collections.UserDict): 'port', 'fwmark', - 'prefix', 'file-prefix', + 'name-format', + 'privkey-path', ] def __init__(self, data, name, peer): @@ -84,11 +85,15 @@ class Interface(collections.UserDict): return self.peer.network @functools.cached_property - def qualified_name(self): - name = f'{self.get('prefix', '')}{self.network.name}' - if self.name: - name += f'-{self.name}' - return name + def formatted_name(self): + return self.format_string(self.get('name-format', '$network$_if')) + + def format_string(self, s): + return string.Template(s).substitute({ + 'network': self.network.name, + 'peer': self.peer.name, + 'if': self.name, + '_if' : f'-{self.name}' if self.name else ''}) def deep_merge(d, src): @@ -150,10 +155,10 @@ def expand_peerspecs(peer, peerspecs): for x in ( auto_peerspecs(peer) if peerspec.get('auto') else [peerspec])] -def gc_if_data(if_, privkeys): +def gc_if_data(if_): if_data = { - 'name': if_.qualified_name, - 'privkey': privkeys.get(if_.network.name, 'FIXME'), + 'name': if_.formatted_name, + 'privkey': get_privkey(if_), 'addrs': ipspecs_to_ips( if_.peer, if_.get('ips', ['{peer/-}']), interface=True), 'port': if_.get('port'), @@ -250,22 +255,22 @@ def buf_to_file(buf, path, mode=None): buf.seek(0) shutil.copyfileobj(buf, f) -def create_if_files(if_, privkeys): - if_data = gc_if_data(if_, privkeys) +def create_if_files(if_): + if_data = gc_if_data(if_) file_prefix = f'out/{if_.get('file-prefix', '')}' if if_.get('type') == 'systemd': buf_to_file( gc_if_systemd_netdev(if_data), - f'{file_prefix}{if_.qualified_name}.netdev', + f'{file_prefix}{if_.formatted_name}.netdev', mode=0o640) buf_to_file( gc_if_systemd_network(if_data), - f'{file_prefix}{if_.qualified_name}.network') + f'{file_prefix}{if_.formatted_name}.network') else: buf_to_file( gc_if_wgquick(if_data), - f'{file_prefix}{if_.qualified_name}.conf') + f'{file_prefix}{if_.formatted_name}.conf') def load_network_peer_interfaces(config, peer): ifs = peer.pop('if', {}) @@ -300,12 +305,17 @@ def load_networks(config): load_network_peers(config, net) return nets -def load_privkeys(): - privkeys = {} - for path in pathlib.Path.home().joinpath('.wg-genconf').glob('*.privkey'): +@functools.cache +def read_privkey(path): + try: with open(path, 'r') as f: - privkeys[path.stem] = f.read().rstrip() - return privkeys + return f.read().rstrip() + except OSError: + return 'FIXME' + +def get_privkey(if_): + return read_privkey(if_.format_string(os.path.expanduser( + if_.get('privkey-path', '~/.wg-genconf/${network}.privkey')))) def main(): conf_file = sys.argv[1] @@ -314,7 +324,6 @@ def main(): with open(conf_file, 'rb') as f: config = tomllib.load(f) networks = load_networks(config) - privkeys = load_privkeys() if not config['peer'].get(peer_name): sys.exit(f"peer '{peer_name}' not configured") @@ -326,6 +335,6 @@ def main(): # config files, useful when an auto-peer interface is being # separately created if if_.get('file', True): - create_if_files(if_, privkeys) + create_if_files(if_) main() |
