test(deploy): Doctor must check the client-address configuration the API runs
Behind the reference proxy the API runs in trusted-proxy mode, but compose.proxy.yaml gives those variables to `api` only. The documented Doctor command runs as `migrate`, so it validated an empty configuration and reported "Direct client-address mode" for an installation that trusts its proxy. That is what the first production installation saw. Fails today: - deploy.test.ts: the proxy overlay gives `migrate` no client-address environment; - doctor.test.ts: the check does not say whose configuration it read; - smoke-deploy.sh: Doctor through the proxy overlay does not report trusted-proxy mode (Docker). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
committed by
The_River
co-authored by
Claude Opus 5.5
parent
fa493365bd
commit
54ac6ab83f
@@ -958,6 +958,21 @@ describe("Ekklesia Doctor diagnostics", () => {
|
|||||||
expect(report.result).toBe("ready-with-warnings");
|
expect(report.result).toBe("ready-with-warnings");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("says whose client-address configuration it checked: this process's, not a running API's", async () => {
|
||||||
|
for (const clientAddress of [
|
||||||
|
undefined,
|
||||||
|
{ header: "x-forwarded-for", mode: "trusted-proxy" as const, trustedProxies: ["10.0.0.1"] },
|
||||||
|
{ header: "x-forwarded-for", mode: "trusted-proxy" as const, trustedProxies: ["bad"] },
|
||||||
|
]) {
|
||||||
|
const report = await diagnoseEkklesia(
|
||||||
|
{ ...options(), ...(clientAddress ? { clientAddress } : {}) },
|
||||||
|
dependencies(),
|
||||||
|
);
|
||||||
|
const details = check(report, "identity.client-address").details;
|
||||||
|
expect(details.some((detail) => detail.includes("environment Doctor runs with"))).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("passes client-address configuration with an explicitly configured trusted-proxy mode", async () => {
|
it("passes client-address configuration with an explicitly configured trusted-proxy mode", async () => {
|
||||||
const report = await diagnoseEkklesia(
|
const report = await diagnoseEkklesia(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -555,12 +555,16 @@ grep -q 'TLS required with certificate and hostname verification (explicit priva
|
|||||||
<<<"$doctor_output" || fail "Doctor did not report verify-full with the private CA."
|
<<<"$doctor_output" || fail "Doctor did not report verify-full with the private CA."
|
||||||
grep -q '✓ Object storage reachable' <<<"$doctor_output" ||
|
grep -q '✓ Object storage reachable' <<<"$doctor_output" ||
|
||||||
fail "Doctor could not reach object storage over HTTPS."
|
fail "Doctor could not reach object storage over HTTPS."
|
||||||
|
# Doctor runs as `migrate`; it must check the client-address configuration the API runs with, which
|
||||||
|
# behind the proxy is trusted-proxy mode, not the direct mode an unconfigured process reports.
|
||||||
|
grep -q 'Trusted-proxy client-address mode' <<<"$doctor_output" ||
|
||||||
|
fail "Doctor did not check the API's trusted-proxy client-address configuration."
|
||||||
for value in "$postgres_password" "$s3_secret_key" "$identity_secret"; do
|
for value in "$postgres_password" "$s3_secret_key" "$identity_secret"; do
|
||||||
if grep -qF -- "$value" <<<"$doctor_output"; then
|
if grep -qF -- "$value" <<<"$doctor_output"; then
|
||||||
fail "Doctor output contains a secret."
|
fail "Doctor output contains a secret."
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo "ok Doctor: READY, verify-full with the private CA, storage reachable, no secret printed"
|
echo "ok Doctor: READY, verify-full with the private CA, storage reachable, the API's client-address mode, no secret printed"
|
||||||
|
|
||||||
api_logs="$("${compose[@]}" logs --no-color api 2>&1)"
|
api_logs="$("${compose[@]}" logs --no-color api 2>&1)"
|
||||||
for value in "$postgres_password" "$s3_secret_key" "$identity_secret" "$owner_password"; do
|
for value in "$postgres_password" "$s3_secret_key" "$identity_secret" "$owner_password"; do
|
||||||
|
|||||||
@@ -153,6 +153,11 @@ describe("reference deployment compose files", () => {
|
|||||||
EKKLESIA_CLIENT_ADDRESS_MODE: "trusted-proxy",
|
EKKLESIA_CLIENT_ADDRESS_MODE: "trusted-proxy",
|
||||||
EKKLESIA_CLIENT_ADDRESS_TRUSTED_PROXIES: `${proxyAddress}/32`,
|
EKKLESIA_CLIENT_ADDRESS_TRUSTED_PROXIES: `${proxyAddress}/32`,
|
||||||
});
|
});
|
||||||
|
// Doctor runs as `migrate`. Given anything else, it validates a configuration the API is not
|
||||||
|
// running, and reports "Direct" for an installation that trusts its proxy.
|
||||||
|
expect(proxyOverlay.services?.migrate?.environment).toEqual(
|
||||||
|
proxyOverlay.services?.api?.environment,
|
||||||
|
);
|
||||||
expect(proxyOverlay.networks?.edge?.ipam?.config).toEqual([
|
expect(proxyOverlay.networks?.edge?.ipam?.config).toEqual([
|
||||||
{
|
{
|
||||||
ip_range: "${EKKLESIA_EDGE_DYNAMIC_RANGE:-10.249.250.0/25}",
|
ip_range: "${EKKLESIA_EDGE_DYNAMIC_RANGE:-10.249.250.0/25}",
|
||||||
|
|||||||
Reference in New Issue
Block a user