Multiple fixes: six beds retired (074), the certificate bed against Pebble and step-ca (020), a coupled-pair spike (066) #45
@@ -41,6 +41,14 @@ const ACME = "/var/lib/acme";
|
||||
*/
|
||||
const AUTHORITY = "ghcr.io/letsencrypt/pebble:2.5.0";
|
||||
|
||||
/**
|
||||
* The second implementation, for the same order (novox/hq 04-ISSUES/020): the certificate
|
||||
* authority the catalogue itself runs, pinned as the catalogue pins it. If the order, the challenge
|
||||
* and the handshake agree here as well as against Pebble, the one thing 020 could not rule out — a
|
||||
* Pebble interop detail — is ruled out; and if they disagree, which side differs is in view.
|
||||
*/
|
||||
const SECOND_AUTHORITY = "smallstep/step-ca@sha256:a2b17872915c193259b75a5474c398326f41bd199f0842093e52cf4182bc8270";
|
||||
|
||||
let instanceId = "";
|
||||
|
||||
function shellQuote(s: string): string {
|
||||
@@ -185,6 +193,59 @@ test("a public name is served with a certificate the mesh did not issue", {
|
||||
assert.match(issuer, new RegExp(NAME), `the certificate is not for the name asked for:\n${issuer}`);
|
||||
});
|
||||
|
||||
test("the same order against a second authority: the catalogue's own certificate authority", {
|
||||
skip, timeout: 900_000,
|
||||
}, async () => {
|
||||
// The proxy that served the first test goes; its cache with it, or the certificate Pebble issued
|
||||
// would be served again and nothing would have been ordered here.
|
||||
await must(`pkill -f mesh-route-proxy || true; sleep 1; mkdir -p ${ACME}/cache2`);
|
||||
|
||||
// The catalogue's authority, as the catalogue runs it: ACME on, listening on its own port, a
|
||||
// root and an intermediate made at first start. It resolves the name through the machine's
|
||||
// resolver, which reads the hosts entry the first test wrote.
|
||||
await must(
|
||||
`docker run -d --name stepca --network host ` +
|
||||
`-e DOCKER_STEPCA_INIT_NAME="Lab CA" -e DOCKER_STEPCA_INIT_DNS_NAMES=localhost,127.0.0.1 ` +
|
||||
`-e DOCKER_STEPCA_INIT_ACME=true -e DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=false ` +
|
||||
`-e DOCKER_STEPCA_INIT_PASSWORD=lab-only-password ${SECOND_AUTHORITY}`,
|
||||
);
|
||||
let ready = false;
|
||||
for (let i = 0; i < 90 && !ready; i++) {
|
||||
({ ok: ready } = await on(`docker exec stepca test -s /home/step/certs/root_ca.crt && curl -sk https://127.0.0.1:9000/health -o /dev/null`));
|
||||
if (!ready) await new Promise((r) => setTimeout(r, 2000));
|
||||
}
|
||||
assert.ok(ready, `the second authority never came up:\n${(await on(`docker logs stepca 2>&1 | tail -30`)).out}`);
|
||||
await must(`docker exec stepca cat /home/step/certs/root_ca.crt > ${ACME}/stepca-root.pem`);
|
||||
|
||||
await must(
|
||||
`ROUTES=${ACME}/routes.json LISTEN=:80 TLS_LISTEN=:443 ` +
|
||||
`ACME_CACHE=${ACME}/cache2 ` +
|
||||
`ACME_DIRECTORY=https://127.0.0.1:9000/acme/acme/directory ` +
|
||||
`ACME_CA_BUNDLE=${ACME}/stepca-root.pem ` +
|
||||
`nohup /usr/local/bin/mesh-route-proxy >${ACME}/proxy2.log 2>&1 & sleep 3`,
|
||||
);
|
||||
|
||||
let served = { out: "", ok: false };
|
||||
for (let i = 0; i < 40 && !served.ok; i++) {
|
||||
served = await on(`curl -sf --cacert ${ACME}/stepca-root.pem https://${NAME}/ `);
|
||||
if (!served.ok) await new Promise((r) => setTimeout(r, 2000));
|
||||
}
|
||||
if (!served.ok) {
|
||||
const proxyLog = (await on(`cat ${ACME}/proxy2.log`)).out;
|
||||
const authority = (await on(`docker logs stepca 2>&1 | tail -40`)).out;
|
||||
assert.fail(
|
||||
`the name was never served over TLS from the second authority: ${served.out}\n\n` +
|
||||
`── the proxy tried:\n${proxyLog}\n── the authority heard:\n${authority}\n`);
|
||||
}
|
||||
assert.match(served.out, /hello/);
|
||||
const issuer = await must(
|
||||
`echo | openssl s_client -connect ${NAME}:443 -servername ${NAME} 2>/dev/null ` +
|
||||
`| openssl x509 -noout -issuer -subject`,
|
||||
);
|
||||
assert.match(issuer, /Lab CA/, `the certificate was not issued by the second authority:\n${issuer}`);
|
||||
assert.match(issuer, new RegExp(NAME), `the certificate is not for the name asked for:\n${issuer}`);
|
||||
});
|
||||
|
||||
test("no certificate is ordered for a name the mesh does not route", {
|
||||
skip, timeout: 300_000,
|
||||
}, async () => {
|
||||
@@ -193,6 +254,6 @@ test("no certificate is ordered for a name the mesh does not route", {
|
||||
const { out } = await on(
|
||||
`echo | openssl s_client -connect 127.0.0.1:443 -servername nobody-asked-for-this.example 2>&1 | head -20`,
|
||||
);
|
||||
assert.doesNotMatch(out, /Pebble/i,
|
||||
assert.doesNotMatch(out, /Pebble|Lab CA/i,
|
||||
`a certificate was obtained for a name nothing routes here:\n${out}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user