Fix: prevent wg0.conf truncation when remove_peer splits blocks
Unit Tests / test (push) Successful in 7m46s
Unit Tests / test (push) Successful in 7m46s
_write_config() was stripping trailing newlines, causing the next
add_cell_peer() to create a single-newline separator between [Interface]
and [Peer] blocks instead of the required blank line. On the following
remove_peer() call, split('\n\n') treated both sections as one block,
matched the PublicKey filter, and wrote an empty string — destroying the
[Interface] section and reverting to the hardcoded SERVER_ADDRESS fallback.
Two-part fix:
1. _write_config() always ends content with a newline
2. remove_peer() normalises single-newline [Peer] headers to blank-line
separators before splitting, and refuses to write if [Interface] would
be lost
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -294,6 +294,8 @@ class WireGuardManager(BaseServiceManager):
|
|||||||
return self.generate_config()
|
return self.generate_config()
|
||||||
|
|
||||||
def _write_config(self, content: str):
|
def _write_config(self, content: str):
|
||||||
|
if content and not content.endswith('\n'):
|
||||||
|
content += '\n'
|
||||||
with open(self._config_file(), 'w') as f:
|
with open(self._config_file(), 'w') as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
self._syncconf()
|
self._syncconf()
|
||||||
@@ -805,12 +807,20 @@ class WireGuardManager(BaseServiceManager):
|
|||||||
"""Remove the [Peer] block matching public_key from wg0.conf."""
|
"""Remove the [Peer] block matching public_key from wg0.conf."""
|
||||||
try:
|
try:
|
||||||
content = self._read_config()
|
content = self._read_config()
|
||||||
# Split on blank lines between blocks
|
# Normalise to ensure blank-line block separators before splitting.
|
||||||
raw_blocks = ('\n' + content).split('\n\n')
|
# Without this, a file written without trailing newline will merge
|
||||||
|
# [Interface] and the first [Peer] into one block, and the filter
|
||||||
|
# below would then delete [Interface] together with the peer.
|
||||||
|
normalised = content.replace('\n[Peer]', '\n\n[Peer]')
|
||||||
|
raw_blocks = ('\n' + normalised).split('\n\n')
|
||||||
new_blocks = [
|
new_blocks = [
|
||||||
b for b in raw_blocks
|
b for b in raw_blocks
|
||||||
if not (f'PublicKey = {public_key}' in b and '[Peer]' in b)
|
if not (f'PublicKey = {public_key}' in b and '[Peer]' in b)
|
||||||
]
|
]
|
||||||
|
# Never write an empty file — that would destroy the [Interface] block.
|
||||||
|
if not any('[Interface]' in b for b in new_blocks):
|
||||||
|
logger.error('remove_peer: [Interface] block would be lost — aborting write')
|
||||||
|
return False
|
||||||
self._write_config('\n\n'.join(new_blocks).lstrip('\n'))
|
self._write_config('\n\n'.join(new_blocks).lstrip('\n'))
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user