mongo/jstests/ocsp/ocsp_server_refresh.js

138 lines
4.0 KiB
JavaScript

// Check that OCSP verification works
// @tags: [requires_http_client, requires_ocsp_stapling]
import {FAULT_REVOKED, MockOCSPServer} from "jstests/ocsp/lib/mock_ocsp.js";
import {
assertClientConnectFails,
assertClientConnectSucceeds,
OCSP_CA_PEM,
OCSP_REVOKED,
OCSP_SERVER_CERT,
supportsStapling,
} from "jstests/ocsp/lib/ocsp_helpers.js";
if (!supportsStapling()) {
quit();
}
let mock_ocsp = new MockOCSPServer("", 20);
mock_ocsp.start();
const ocsp_options = {
tlsMode: "requireTLS",
tlsCertificateKeyFile: OCSP_SERVER_CERT,
tlsCAFile: OCSP_CA_PEM,
tlsAllowInvalidHostnames: "",
setParameter: {
"ocspEnabled": "true",
},
};
let conn = null;
assert.doesNotThrow(() => {
conn = MongoRunner.runMongod(ocsp_options);
});
mock_ocsp.stop();
mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 1000);
mock_ocsp.start();
// We're sleeping here to give the server enough time to fetch a new OCSP response
// saying that it's revoked.
sleep(15000);
assertClientConnectFails(conn, OCSP_REVOKED);
mock_ocsp.stop();
mock_ocsp = new MockOCSPServer("", 1000);
mock_ocsp.start();
// This ensures that the client was viewing a stapled response.
assertClientConnectFails(conn, OCSP_REVOKED);
MongoRunner.stopMongod(conn);
// have the server refresh its response every 10 seconds
Object.extend(ocsp_options, {setParameter: {ocspEnabled: true, ocspValidationRefreshPeriodSecs: 10}});
assert.doesNotThrow(() => {
conn = MongoRunner.runMongod(ocsp_options);
});
// Have the OCSP server revoke the certificate. Clients should observe a refreshed stapled response
// after ocspValidationRefreshPeriodSecs
mock_ocsp.stop();
mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 10);
mock_ocsp.start();
sleep(30000);
// the client should be trying to connect after its certificate has been revoked.
assertClientConnectFails(conn, OCSP_REVOKED);
MongoRunner.stopMongod(conn);
// The mongoRunner spawns a new Mongo Object to validate the collections which races
// with the shutdown logic of the mock_ocsp responder on some platforms. We need this
// sleep to make sure that the threads don't interfere with each other.
sleep(1000);
mock_ocsp.stop();
// Next, we're going to test that the server deletes its OCSP response before the
// response expires.
const NEXT_UPDATE = 10;
mock_ocsp = new MockOCSPServer("", NEXT_UPDATE);
mock_ocsp.start();
assert.doesNotThrow(() => {
conn = MongoRunner.runMongod(ocsp_options);
});
mock_ocsp.stop();
// If the server stapled an expired response, then the client would refuse to connect.
// We now check that the server has not stapled a response.
sleep(NEXT_UPDATE * 1000);
assertClientConnectSucceeds(conn);
MongoRunner.stopMongod(conn);
// Make sure that the refresh period is set to a very large value so that we can
// make sure that the period defined by the mock OCSP responder overrides it.
let ocsp_options_high_refresh = {
tlsMode: "requireTLS",
tlsCertificateKeyFile: OCSP_SERVER_CERT,
tlsCAFile: OCSP_CA_PEM,
tlsAllowInvalidHostnames: "",
setParameter: {
"ocspEnabled": "true",
"ocspStaplingRefreshPeriodSecs": 300000,
},
};
mock_ocsp = new MockOCSPServer("", 10);
mock_ocsp.start();
assert.doesNotThrow(() => {
conn = MongoRunner.runMongod(ocsp_options);
});
// Kill the ocsp responder, start it with cert revoked, and wait 20 seconds
// so the server refreshes its stapled OCSP response.
mock_ocsp.stop();
mock_ocsp = new MockOCSPServer(FAULT_REVOKED, 100);
mock_ocsp.start();
sleep(20000);
// By asserting here that a new connection cannot be established to the
// mongod, we prove that the server has refreshed its stapled response sooner
// than the refresh period indicated.
assertClientConnectFails(conn, OCSP_REVOKED);
MongoRunner.stopMongod(conn);
// The mongoRunner spawns a new Mongo Object to validate the collections which races
// with the shutdown logic of the mock_ocsp responder on some platforms. We need this
// sleep to make sure that the threads don't interfere with each other.
sleep(1000);
mock_ocsp.stop();