mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 21:26:44 +00:00
fix(test-e2e-playwright): judge HSTS on the app's own response, not the SSO page
gotoOnion follows the redirect chain, so a front page behind oauth2-proxy returned the Keycloak login page and expectHstsWhenTls read the issuer's headers. On an onion pick the clearnet issuer's HSTS then failed the 'must not emit HSTS over plaintext onion transport' assertion although the onion vhost sent none. Add ownResponseHeaders, which walks redirectedFrom() back to the first response, and use it in the eight specs whose front page redirects to SSO: lam, kix, magento, openproject, pgadmin, phpldapadmin, phpmyadmin and pihole. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6759d795a6
commit
529876c7ca
9 files changed
+32
-25
No files matched your search
@@ -30,4 +30,19 @@ function expectHstsWhenTls(headers, baseUrl, label) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { isTlsBaseUrl, expectHstsWhenTls };
|
||||
/**
|
||||
* Headers of the first response a navigation received, before any redirect.
|
||||
*
|
||||
* @param {import("@playwright/test").Response} response final navigation response
|
||||
* @returns {Promise<Record<string, string>>} headers the app's own vhost sent
|
||||
*/
|
||||
async function ownResponseHeaders(response) {
|
||||
let request = response.request();
|
||||
while (request.redirectedFrom()) {
|
||||
request = request.redirectedFrom();
|
||||
}
|
||||
const own = await request.response();
|
||||
return (own || response).headers();
|
||||
}
|
||||
|
||||
module.exports = { isTlsBaseUrl, expectHstsWhenTls, ownResponseHeaders };
|
||||
@@ -1,12 +1,11 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
|
||||
exports.register = function (shared) {
|
||||
test("kix root emits TLS+HSTS", async ({ page }) => {
|
||||
const response = await gotoOnion(page, `${shared.env.appBaseUrl}/`);
|
||||
expect(response, "Expected a response from the KIX root").toBeTruthy();
|
||||
expect(response.status(), "Expected KIX root status < 500").toBeLessThan(500);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, shared.env.appBaseUrl, "kix");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), shared.env.appBaseUrl, "kix");
|
||||
});
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("LAM front page is served under canonical domain with TLS", async ({ page }
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the LAM URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "LAM");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "LAM");
|
||||
});
|
||||
|
||||
test("LAM returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("Magento front page is served under canonical domain with TLS", async ({ pa
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the Magento URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "Magento");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "Magento");
|
||||
});
|
||||
|
||||
test("Magento returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("OpenProject front page is served under canonical domain with TLS", async (
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the OpenProject URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "OpenProject");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "OpenProject");
|
||||
});
|
||||
|
||||
test("OpenProject returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("pgAdmin front page is served under canonical domain with TLS", async ({ pa
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the pgAdmin URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "pgAdmin");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "pgAdmin");
|
||||
});
|
||||
|
||||
test("pgAdmin returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("phpLDAPadmin front page is served under canonical domain with TLS", async
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the phpLDAPadmin URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "phpLDAPadmin");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "phpLDAPadmin");
|
||||
});
|
||||
|
||||
test("phpLDAPadmin returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { decodeDotenvQuotedValue, normalizeBaseUrl, runAdminFlow, runBiberFlow, runGuestFlow , expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
const appBaseUrl = normalizeBaseUrl(process.env.APP_BASE_URL || "");
|
||||
@@ -21,8 +21,7 @@ test("phpMyAdmin front page is served under canonical domain with TLS", async ({
|
||||
response.url().includes(canonicalDomain),
|
||||
`Expected canonical domain "${canonicalDomain}" to back the phpMyAdmin URL`
|
||||
).toBe(true);
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, appBaseUrl, "phpMyAdmin");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), appBaseUrl, "phpMyAdmin");
|
||||
});
|
||||
|
||||
test("phpMyAdmin returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { resolveTimeout } = require("./timeouts");
|
||||
const { expectHstsWhenTls, gotoOnion } = require("./personas");
|
||||
const { expectHstsWhenTls, ownResponseHeaders, gotoOnion } = require("./personas");
|
||||
|
||||
test.use({ ignoreHTTPSErrors: true });
|
||||
|
||||
@@ -31,8 +31,7 @@ test("Pi-hole front page is served under canonical domain with TLS", async ({ pa
|
||||
`Expected canonical domain "${canonicalDomain}" to back the Pi-hole URL`
|
||||
).toBe(true);
|
||||
}
|
||||
const headers = response.headers();
|
||||
expectHstsWhenTls(headers, piholeBaseUrl, "Pi-hole");
|
||||
expectHstsWhenTls(await ownResponseHeaders(response), piholeBaseUrl, "Pi-hole");
|
||||
});
|
||||
|
||||
test("Pi-hole returns HTML content under canonical domain", async ({ request }) => {
|
||||
|
||||
Reference in new issue
Block a user