fix(scan): generate valid systemd working directory

This commit is contained in:
2026-09-24 17:06:52 +02:00
parent 8e1505023b
commit dde46f10e1
3 changed files with 11 additions and 3 deletions

View File

@@ -81,7 +81,9 @@ def unit_quote(value):
unit_path.write_text('\n'.join([ unit_path.write_text('\n'.join([
'[Unit]', 'Description=FEDEO Scan-Agent', 'After=network-online.target', '', '[Unit]', 'Description=FEDEO Scan-Agent', 'After=network-online.target', '',
'[Service]', 'Type=simple', '[Service]', 'Type=simple',
'WorkingDirectory=' + unit_quote(agent_dir), # WorkingDirectory takes a literal path, unlike Environment/ExecStart.
# Quotes would become part of the path; only systemd specifiers need escaping.
'WorkingDirectory=' + str(agent_dir).replace('%', '%%'),
'Environment=' + unit_quote('FEDEO_AGENT_ENV=' + str(config_path)), 'Environment=' + unit_quote('FEDEO_AGENT_ENV=' + str(config_path)),
'ExecStart=' + unit_quote(node) + ' ' + unit_quote(agent_dir / 'dist/main.js'), 'ExecStart=' + unit_quote(node) + ' ' + unit_quote(agent_dir / 'dist/main.js'),
'Restart=on-failure', 'RestartSec=5', 'UMask=0077', '', 'Restart=on-failure', 'RestartSec=5', 'UMask=0077', '',

View File

@@ -14,6 +14,8 @@ const agentId = 'b48c0e33-1abd-4b11-89fa-1bb7b39a3057'
const token = 'fedeo_agent_' + 'a'.repeat(64) const token = 'fedeo_agent_' + 'a'.repeat(64)
const options = { agentId, token, backendUrl: 'https://fedeo.example.com/backend', autostart: true } const options = { agentId, token, backendUrl: 'https://fedeo.example.com/backend', autostart: true }
const execute = promisify(execFile) const execute = promisify(execFile)
const hasSystemdAnalyze = process.platform === 'linux' && await execute('systemd-analyze', ['--version'])
.then(() => true, error => { if (error.code === 'ENOENT') return false; throw error })
test('backend URLs preserve reverse-proxy paths and reject credentials or non-HTTP protocols', () => { test('backend URLs preserve reverse-proxy paths and reject credentials or non-HTTP protocols', () => {
assert.equal(agentBackendUrl('/backend/', 'https://fedeo.example.com'), options.backendUrl) assert.equal(agentBackendUrl('/backend/', 'https://fedeo.example.com'), options.backendUrl)
@@ -70,9 +72,13 @@ for (const start of [false, true]) {
for (const [file, encoded] of Object.entries(bundle.files)) { for (const [file, encoded] of Object.entries(bundle.files)) {
assert.equal((await readFile(path.join(agentDir, file))).toString('base64'), encoded) assert.equal((await readFile(path.join(agentDir, file))).toString('base64'), encoded)
} }
const unit = await readFile(path.join(env.XDG_CONFIG_HOME, 'systemd/user', 'fedeo-device-agent-' + agentId + '.service'), 'utf8') const unitPath = path.join(env.XDG_CONFIG_HOME, 'systemd/user', 'fedeo-device-agent-' + agentId + '.service')
const unit = await readFile(unitPath, 'utf8')
assert.ok(unit.includes('data with spaces %%')) assert.ok(unit.includes('data with spaces %%'))
assert.ok(!unit.includes(token)) assert.ok(!unit.includes(token))
await t.test('systemd accepts the generated service, including a working directory with spaces and percent signs', { skip: !hasSystemdAnalyze }, async () => {
await execute('systemd-analyze', ['--user', 'verify', unitPath])
})
const calls = await readFile(env.FEDEO_TEST_SYSTEMD_LOG, 'utf8') const calls = await readFile(env.FEDEO_TEST_SYSTEMD_LOG, 'utf8')
assert.equal(calls.includes('--user enable fedeo-device-agent-'), start) assert.equal(calls.includes('--user enable fedeo-device-agent-'), start)
assert.equal(calls.includes('--user restart fedeo-device-agent-'), start) assert.equal(calls.includes('--user restart fedeo-device-agent-'), start)

File diff suppressed because one or more lines are too long