Полный продовый фикс fix22: DNS preflight, inet firewall, idempotent bootstrap, auth-semantics и redact-config
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { RuntimeContext } from "../types/context";
|
||||
import { readText, renderTemplate, writeTextAtomic } from "../lib/fs";
|
||||
import { fileExists, readText, renderTemplate, writeTextAtomic } from "../lib/fs";
|
||||
import { runVisible } from "../lib/process";
|
||||
|
||||
export async function writePostInstallEnv(context: RuntimeContext): Promise<void> {
|
||||
const rendered = renderTemplate(await readText(`${context.options.packageDir}/templates/env/post-install.env.tpl`), {
|
||||
@@ -54,3 +55,17 @@ export async function writeBootstrapAdminSecret(context: RuntimeContext): Promis
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function ensureBootstrapAdminSecret(context: RuntimeContext): Promise<void> {
|
||||
const path = context.config.bootstrapAdminSecretPath;
|
||||
if (!(await fileExists(path))) {
|
||||
await writeBootstrapAdminSecret(context);
|
||||
return;
|
||||
}
|
||||
|
||||
await runVisible`test "$(stat -c '%U:%G' ${path})" = 'root:root'`;
|
||||
await runVisible`test "$(stat -c '%a' ${path})" = '600'`;
|
||||
await runVisible`grep -q '^ADMIN_USER=' ${path}`;
|
||||
await runVisible`grep -q '^ADMIN_INITIAL_PASSWORD=' ${path}`;
|
||||
await runVisible`grep -q '^ADMIN_CON_PASS=' ${path}`;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ export async function applyFirewall(context: RuntimeContext): Promise<void> {
|
||||
|
||||
const acmeChallengePort = context.config.acmeType === "tls" ? 443 : 80;
|
||||
const acmeRule = context.config.tlsMode === "acme"
|
||||
? `tcp dport ${acmeChallengePort} accept`
|
||||
? `meta nfproto ipv4 tcp dport ${acmeChallengePort} accept`
|
||||
: "# acme challenge port disabled";
|
||||
|
||||
const rendered = renderTemplate(await readText(`${context.options.packageDir}/templates/nftables/hy2xs.nft.tpl`), {
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
import type { RuntimeContext } from "../types/context";
|
||||
import { resolve4, resolve6 } from "node:dns/promises";
|
||||
import { dirExists, fileExists } from "../lib/fs";
|
||||
import { fail, info } from "../lib/log";
|
||||
import { run } from "../lib/process";
|
||||
import { assertPlatform } from "../platform/assert";
|
||||
|
||||
function isNoDnsRecords(error: unknown): boolean {
|
||||
return (
|
||||
typeof error === "object" &&
|
||||
error !== null &&
|
||||
"code" in error &&
|
||||
(((error as { code?: string }).code === "ENODATA") || ((error as { code?: string }).code === "ENOTFOUND"))
|
||||
);
|
||||
}
|
||||
|
||||
async function isTcpPortListening(port: number): Promise<boolean> {
|
||||
try {
|
||||
const output = await run`ss -H -ltn`;
|
||||
@@ -114,23 +124,28 @@ export async function preflight(context: RuntimeContext): Promise<void> {
|
||||
}
|
||||
|
||||
if (context.config.domain) {
|
||||
let a: string[] = [];
|
||||
try {
|
||||
const a = await run`getent ahostsv4 ${context.config.domain}`;
|
||||
if (!a.trim()) {
|
||||
fail(`domain has no A-record: ${context.config.domain}`);
|
||||
}
|
||||
a = await resolve4(context.config.domain);
|
||||
} catch {
|
||||
fail(`domain has no A-record: ${context.config.domain}`);
|
||||
}
|
||||
if (a.length === 0) {
|
||||
fail(`domain has no A-record: ${context.config.domain}`);
|
||||
}
|
||||
|
||||
let aaaa: string[] = [];
|
||||
try {
|
||||
const aaaa = await run`getent ahostsv6 ${context.config.domain}`;
|
||||
if (aaaa.trim()) {
|
||||
fail(
|
||||
`domain ${context.config.domain} has AAAA record while HY2XS profile is IPv4-only; remove AAAA record before install`
|
||||
);
|
||||
aaaa = await resolve6(context.config.domain);
|
||||
} catch (error) {
|
||||
if (!isNoDnsRecords(error)) {
|
||||
fail(`DNS AAAA lookup failed for ${context.config.domain}: ${String(error)}`);
|
||||
}
|
||||
} catch {
|
||||
// no AAAA is acceptable
|
||||
}
|
||||
if (aaaa.length > 0) {
|
||||
fail(
|
||||
`domain ${context.config.domain} has DNS AAAA record while HY2XS profile is IPv4-only; remove AAAA record before install`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user