mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): prove security administration custody live
This commit is contained in:
+13
-2
@@ -119,13 +119,23 @@ function sameFileState(
|
||||
);
|
||||
}
|
||||
|
||||
export function isClusterAdministrationProjectedSourceDirectoryAuthority(
|
||||
status: Readonly<{ mode: number; uid: number }>,
|
||||
): boolean {
|
||||
const permissions = status.mode & 0o1777;
|
||||
return (
|
||||
(permissions & 0o002) === 0 ||
|
||||
(status.uid === 0 && permissions === 0o1777)
|
||||
);
|
||||
}
|
||||
|
||||
function verifySourceDirectory(sourceDirectory: string): string {
|
||||
const status = lstatSync(sourceDirectory, { throwIfNoEntry: false });
|
||||
if (
|
||||
status === undefined ||
|
||||
!status.isDirectory() ||
|
||||
status.isSymbolicLink() ||
|
||||
(status.mode & 0o002) !== 0
|
||||
!isClusterAdministrationProjectedSourceDirectoryAuthority(status)
|
||||
) {
|
||||
throw new ClusterAdministrationKubernetesInputStageError(
|
||||
'projected source directory authority is invalid',
|
||||
@@ -245,7 +255,7 @@ function verifyWritableParent(parent: string, label: string): void {
|
||||
status === undefined ||
|
||||
!status.isDirectory() ||
|
||||
status.isSymbolicLink() ||
|
||||
(status.mode & 0o002) !== 0
|
||||
!isClusterAdministrationProjectedSourceDirectoryAuthority(status)
|
||||
) {
|
||||
throw new ClusterAdministrationKubernetesInputStageError(
|
||||
`${label} parent authority is invalid`,
|
||||
@@ -290,6 +300,7 @@ function createPrivateDirectory(directory: string, label: string): void {
|
||||
}
|
||||
|
||||
function prepareDeliveryDirectory(directory: string): void {
|
||||
verifyWritableParent(dirname(directory), 'delivery directory');
|
||||
const existing = lstatSync(directory, { throwIfNoEntry: false });
|
||||
if (existing === undefined) {
|
||||
createPrivateDirectory(directory, 'delivery directory');
|
||||
|
||||
@@ -17,6 +17,7 @@ const { afterEach, test } = require('node:test');
|
||||
|
||||
const {
|
||||
ClusterAdministrationKubernetesInputStageError,
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority,
|
||||
stageClusterAdministrationKubernetesInputs,
|
||||
} = require('../dist/security-administration/clusterAdministrationKubernetesInputStage.js');
|
||||
|
||||
@@ -87,6 +88,44 @@ test('copies a Kubernetes projected Secret into a private immutable input bounda
|
||||
assert.equal(JSON.stringify(result).includes('A'.repeat(43)), false);
|
||||
});
|
||||
|
||||
test('accepts only the exact root-owned sticky Kubernetes mount authority', () => {
|
||||
assert.equal(
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority({
|
||||
mode: 0o41777,
|
||||
uid: 0,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority({
|
||||
mode: 0o43777,
|
||||
uid: 0,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority({
|
||||
mode: 0o40777,
|
||||
uid: 0,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority({
|
||||
mode: 0o41777,
|
||||
uid: 10001,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
isClusterAdministrationProjectedSourceDirectoryAuthority({
|
||||
mode: 0o40755,
|
||||
uid: 10001,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('prepares a private persistent delivery directory without weakening it', () => {
|
||||
const fixture = projectedInput();
|
||||
|
||||
@@ -109,6 +148,26 @@ test('prepares a private persistent delivery directory without weakening it', ()
|
||||
assert.equal(mode(fixture.deliveryDirectory), 0o700);
|
||||
});
|
||||
|
||||
test('rejects a precreated private delivery directory under an unsafe parent', () => {
|
||||
const fixture = projectedInput();
|
||||
const unsafeParent = join(fixture.root, 'unsafe-delivery-parent');
|
||||
mkdirSync(unsafeParent, { mode: 0o777 });
|
||||
chmodSync(unsafeParent, 0o777);
|
||||
const deliveryDirectory = join(unsafeParent, 'private');
|
||||
mkdirSync(deliveryDirectory, { mode: 0o700 });
|
||||
|
||||
assert.throws(
|
||||
() =>
|
||||
stageClusterAdministrationKubernetesInputs({
|
||||
sourceDirectory: fixture.sourceDirectory,
|
||||
targetDirectory: fixture.targetDirectory,
|
||||
deliveryDirectory,
|
||||
}),
|
||||
/delivery directory parent authority is invalid/,
|
||||
);
|
||||
assert.equal(mode(deliveryDirectory), 0o700);
|
||||
});
|
||||
|
||||
test('rejects a projected input symlink that escapes the Secret authority', () => {
|
||||
const fixture = projectedInput();
|
||||
const external = join(fixture.root, 'external-command.json');
|
||||
|
||||
Reference in New Issue
Block a user