mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-23 12:05:27 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
const { test } = require('node:test');
|
||||
const {
|
||||
POSTGRES_CA_MAX_CERTIFICATES,
|
||||
POSTGRES_CA_MAX_FILE_BYTES,
|
||||
PostgresCertificateAuthorityFileError,
|
||||
inspectPostgresCertificateAuthorityFile,
|
||||
loadPostgresCertificateAuthorityFile,
|
||||
} = require('@qinglong/cluster-postgres/runtime');
|
||||
|
||||
const FIXTURES = path.resolve(
|
||||
__dirname,
|
||||
'../../ql3-cluster-control/test/fixtures/mtls',
|
||||
);
|
||||
const CA = fs.readFileSync(path.join(FIXTURES, 'ca-cert.pem'), 'utf8');
|
||||
|
||||
function temporaryDirectory(t) {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-pg-ca-'));
|
||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
||||
return directory;
|
||||
}
|
||||
|
||||
function expectCode(callback, code) {
|
||||
assert.throws(
|
||||
callback,
|
||||
(error) =>
|
||||
error instanceof PostgresCertificateAuthorityFileError &&
|
||||
error.code === code,
|
||||
);
|
||||
}
|
||||
|
||||
test('loads a bounded CA bundle through a projected-Secret symlink', (t) => {
|
||||
const directory = temporaryDirectory(t);
|
||||
const dataDirectory = path.join(directory, '..data');
|
||||
fs.mkdirSync(dataDirectory);
|
||||
fs.writeFileSync(path.join(dataDirectory, 'ca.crt'), CA, { mode: 0o444 });
|
||||
fs.symlinkSync(path.join('..data', 'ca.crt'), path.join(directory, 'ca.crt'));
|
||||
|
||||
const bundle = loadPostgresCertificateAuthorityFile(
|
||||
path.join(directory, 'ca.crt'),
|
||||
);
|
||||
assert.match(bundle, /^-----BEGIN CERTIFICATE-----/);
|
||||
assert.match(bundle, /-----END CERTIFICATE-----\n$/);
|
||||
|
||||
const inspection = inspectPostgresCertificateAuthorityFile(
|
||||
path.join(directory, 'ca.crt'),
|
||||
);
|
||||
assert.equal(inspection.bundle, bundle);
|
||||
assert.equal(inspection.fingerprints256.length, 1);
|
||||
assert.match(
|
||||
inspection.fingerprints256[0],
|
||||
/^(?:[0-9A-F]{2}:){31}[0-9A-F]{2}$/,
|
||||
);
|
||||
assert.equal(Object.isFrozen(inspection), true);
|
||||
assert.equal(Object.isFrozen(inspection.fingerprints256), true);
|
||||
});
|
||||
|
||||
test('rejects ambiguous paths, file types, permissions and sizes', (t) => {
|
||||
const directory = temporaryDirectory(t);
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile('relative-ca.pem'),
|
||||
'QL3_POSTGRES_CA_INVALID_PATH',
|
||||
);
|
||||
expectCode(
|
||||
() =>
|
||||
loadPostgresCertificateAuthorityFile(path.join(directory, 'missing.pem')),
|
||||
'QL3_POSTGRES_CA_UNAVAILABLE',
|
||||
);
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(directory),
|
||||
'QL3_POSTGRES_CA_NOT_REGULAR',
|
||||
);
|
||||
|
||||
const writable = path.join(directory, 'writable.pem');
|
||||
fs.writeFileSync(writable, CA, { mode: 0o666 });
|
||||
fs.chmodSync(writable, 0o666);
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(writable),
|
||||
'QL3_POSTGRES_CA_INSECURE_PERMISSIONS',
|
||||
);
|
||||
|
||||
const oversized = path.join(directory, 'oversized.pem');
|
||||
fs.writeFileSync(oversized, Buffer.alloc(POSTGRES_CA_MAX_FILE_BYTES + 1), {
|
||||
mode: 0o444,
|
||||
});
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(oversized),
|
||||
'QL3_POSTGRES_CA_INVALID_SIZE',
|
||||
);
|
||||
});
|
||||
|
||||
test('rejects malformed, non-CA, duplicate and oversized bundles', (t) => {
|
||||
const directory = temporaryDirectory(t);
|
||||
const malformed = path.join(directory, 'malformed.pem');
|
||||
fs.writeFileSync(malformed, `${CA}\nunreviewed`, { mode: 0o444 });
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(malformed),
|
||||
'QL3_POSTGRES_CA_INVALID_PEM',
|
||||
);
|
||||
|
||||
const nonCa = path.join(directory, 'non-ca.pem');
|
||||
fs.copyFileSync(path.join(FIXTURES, 'server-cert.pem'), nonCa);
|
||||
fs.chmodSync(nonCa, 0o444);
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(nonCa),
|
||||
'QL3_POSTGRES_CA_NOT_CA',
|
||||
);
|
||||
|
||||
const duplicate = path.join(directory, 'duplicate.pem');
|
||||
fs.writeFileSync(duplicate, `${CA}\n${CA}`, { mode: 0o444 });
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(duplicate),
|
||||
'QL3_POSTGRES_CA_DUPLICATE_CERTIFICATE',
|
||||
);
|
||||
|
||||
const tooMany = path.join(directory, 'too-many.pem');
|
||||
fs.writeFileSync(
|
||||
tooMany,
|
||||
Array.from({ length: POSTGRES_CA_MAX_CERTIFICATES + 1 }, () => CA).join(
|
||||
'\n',
|
||||
),
|
||||
{ mode: 0o444 },
|
||||
);
|
||||
expectCode(
|
||||
() => loadPostgresCertificateAuthorityFile(tooMany),
|
||||
'QL3_POSTGRES_CA_TOO_MANY_CERTIFICATES',
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user