Repository files, collaboration, releases and project activity.
ARCHFORGE HISTORY
Blame · tests/domain-setup.test.js
Branch main · the Commit author is not necessarily a verified ArchForge account.
b8619f148earchadmin2026-10-11
1 'use strict';b8619f148earchadmin2026-10-11
2 const test=require('node:test');b8619f148earchadmin2026-10-11
3 const assert=require('node:assert/strict');b8619f148earchadmin2026-10-11
4 const fs=require('node:fs');b8619f148earchadmin2026-10-11
5 const os=require('node:os');b8619f148earchadmin2026-10-11
6 const path=require('node:path');b8619f148earchadmin2026-10-11
7 const {spawnSync}=require('node:child_process');b8619f148earchadmin2026-10-11
8 const LIB=path.resolve(__dirname,'../scripts/domain-lib.sh');b8619f148earchadmin2026-10-11
9 function run(cmd,args=[]){b8619f148earchadmin2026-10-11
10 return spawnSync('bash',['-c',`set -Eeuo pipefail; source "$1"; ${cmd}`,'bash',LIB,...args],{encoding:'utf8'});b8619f148earchadmin2026-10-11
11 }b8619f148earchadmin2026-10-11
12 test('valid DNS hostnames only (reject injection, wildcards, invalid labels)',()=>{b8619f148earchadmin2026-10-11
13 for(const hostname of ['status.archforge.nl','sub-domain.example.org','a.b']){b8619f148earchadmin2026-10-11
14 const out=run('af_valid_domain "$2"',[hostname]);b8619f148earchadmin2026-10-11
15 assert.equal(out.status,0,`${hostname}: ${out.stderr}`);b8619f148earchadmin2026-10-11
16 }b8619f148earchadmin2026-10-11
17 for(const hostname of ['localhost','-bad.example','bad-.example','bad..example','a.b;rm -rf /','*.example.com','a_underscore.com','a'.repeat(64)+'.com','example.com\nimport /etc/passwd']){b8619f148earchadmin2026-10-11
18 assert.notEqual(run('af_valid_domain "$2"',[hostname]).status,0,hostname);b8619f148earchadmin2026-10-11
19 }b8619f148earchadmin2026-10-11
20 });b8619f148earchadmin2026-10-11
21 test('IPv4/IPv6 and ACME e-mail validation',()=>{b8619f148earchadmin2026-10-11
22 assert.equal(run('af_valid_ipv4 "$2"',['203.0.113.42']).status,0);b8619f148earchadmin2026-10-11
23 assert.notEqual(run('af_valid_ipv4 "$2"',['256.1.2.3']).status,0);b8619f148earchadmin2026-10-11
24 assert.notEqual(run('af_valid_ipv4 "$2"',['01.2.3.4']).status,0);b8619f148earchadmin2026-10-11
25 assert.equal(run('af_valid_ipv6 "$2"',['2001:db8::1']).status,0);b8619f148earchadmin2026-10-11
26 assert.notEqual(run('af_valid_ipv6 "$2"',['anything']).status,0);b8619f148earchadmin2026-10-11
27 assert.equal(run('af_valid_email "$2"',['ops@example.org']).status,0);b8619f148earchadmin2026-10-11
28 assert.notEqual(run('af_valid_email "$2"',['ops@example.org\nmalicious']).status,0);b8619f148earchadmin2026-10-11
29 });b8619f148earchadmin2026-10-11
30 test('Caddy site snippet cannot inject directives',()=>{b8619f148earchadmin2026-10-11
31 const valid=run('af_render_caddy "$2" "$3"',['status.archforge.nl','ops@example.org']);b8619f148earchadmin2026-10-11
32 assert.equal(valid.status,0);b8619f148earchadmin2026-10-11
33 assert.match(valid.stdout,/^status\.archforge\.nl \{/);b8619f148earchadmin2026-10-11
34 assert.match(valid.stdout,/reverse_proxy 127\.0\.0\.1:3000/);b8619f148earchadmin2026-10-11
35 assert.match(valid.stdout,/tls ops@example\.org/);b8619f148earchadmin2026-10-11
36 assert.notEqual(run('af_render_caddy "$2" "$3"',['example.org\nfoo {','']).status,0);b8619f148earchadmin2026-10-11
37 });b8619f148earchadmin2026-10-11
38 test('domain change preserves all secrets, permissions and existing non-domain lines',()=>{b8619f148earchadmin2026-10-11
39 const dir=fs.mkdtempSync(path.join(os.tmpdir(),'archforge-domain-'));b8619f148earchadmin2026-10-11
40 try{b8619f148earchadmin2026-10-11
41 const env=path.join(dir,'status.env');b8619f148earchadmin2026-10-11
42 fs.writeFileSync(env,'NODE_ENV=production\nSTATUS_PUBLIC_URL=https://old.example.org\nSTATUS_ENCRYPTION_KEY=aabbcc\nSMTP_PASSWORD=very#private=secret\n');b8619f148earchadmin2026-10-11
43 fs.chmodSync(env,0o640);b8619f148earchadmin2026-10-11
44 const res=run('af_set_public_domain "$2" "$3"; af_read_public_domain "$2"',[env,'status.archforge.nl']);b8619f148earchadmin2026-10-11
45 assert.equal(res.status,0,res.stderr);b8619f148earchadmin2026-10-11
46 assert.equal(res.stdout,'status.archforge.nl');b8619f148earchadmin2026-10-11
47 const body=fs.readFileSync(env,'utf8');b8619f148earchadmin2026-10-11
48 assert.match(body,/STATUS_PUBLIC_URL=https:\/\/status\.archforge\.nl/);b8619f148earchadmin2026-10-11
49 assert.match(body,/STATUS_ENCRYPTION_KEY=aabbcc/);b8619f148earchadmin2026-10-11
50 assert.match(body,/SMTP_PASSWORD=very#private=secret/);b8619f148earchadmin2026-10-11
51 assert.equal(fs.statSync(env).mode & 0o777,0o640);b8619f148earchadmin2026-10-11
52 assert.equal(body.match(/^STATUS_PUBLIC_URL=/gm).length,1);b8619f148earchadmin2026-10-11
53 } finally{fs.rmSync(dir,{recursive:true,force:true});}b8619f148earchadmin2026-10-11
54 });b8619f148earchadmin2026-10-11
55 test('SSL script cannot be run in wrong environment or as non-root',()=>{b8619f148earchadmin2026-10-11
56 const script=path.resolve(__dirname,'../configure-domain.sh');b8619f148earchadmin2026-10-11
57 const data=fs.readFileSync(script,'utf8');b8619f148earchadmin2026-10-11
58 assert.match(data,/scripts\/configure-domain\.sh/);b8619f148earchadmin2026-10-11
59 const source=fs.readFileSync(path.resolve(__dirname,'../scripts/configure-domain.sh'),'utf8');b8619f148earchadmin2026-10-11
60 assert.match(source,/Debian 13 only/);b8619f148earchadmin2026-10-11
61 assert.match(source,/Caddy validation failed/);b8619f148earchadmin2026-10-11
62 assert.match(source,/TLS: NOT YET VERIFIED/);b8619f148earchadmin2026-10-11
63 assert.match(source,/restore_previous/);b8619f148earchadmin2026-10-11
64 });