feat(opsserver): add health, audit, cluster health, and durable credential management hardening

This commit is contained in:
2026-04-30 07:10:21 +00:00
parent c3e5cabe3d
commit f4e5f02d0c
34 changed files with 1722 additions and 320 deletions
+80 -13
View File
@@ -1,7 +1,14 @@
import * as plugins from '../../plugins.ts';
import type { OpsServer } from '../classes.opsserver.ts';
import * as interfaces from '../../../ts_interfaces/index.ts';
import { requireValidIdentity } from '../helpers/guards.ts';
import { requireAdminIdentity, requireValidIdentity } from '../helpers/guards.ts';
const getStorageErrorCode = (error: unknown): string | undefined => {
if (!(error instanceof Error)) {
return undefined;
}
return (error as Error & { Code?: string }).Code || error.name;
};
export class BucketsHandler {
public typedrouter = new plugins.typedrequest.TypedRouter();
@@ -29,8 +36,27 @@ export class BucketsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateBucket>(
'createBucket',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.objectStorageRef.createBucket(dataArg.bucketName);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
try {
await this.opsServerRef.objectStorageRef.createBucket(dataArg.bucketName);
await this.opsServerRef.objectStorageRef.auditLogger.log({
actorUserId: dataArg.identity.userId,
action: 'bucket.create',
targetType: 'bucket',
targetId: dataArg.bucketName,
success: true,
});
} catch (error) {
await this.opsServerRef.objectStorageRef.auditLogger.log({
actorUserId: dataArg.identity.userId,
action: 'bucket.create',
targetType: 'bucket',
targetId: dataArg.bucketName,
success: false,
message: error instanceof Error ? error.message : String(error),
});
throw error;
}
return { ok: true };
},
),
@@ -41,9 +67,25 @@ export class BucketsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteBucket>(
'deleteBucket',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.objectStorageRef.deleteBucket(dataArg.bucketName);
await this.opsServerRef.objectStorageRef.policyManager.onBucketDeleted(dataArg.bucketName);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
try {
await this.opsServerRef.objectStorageRef.deleteBucket(dataArg.bucketName);
} catch (error) {
if (getStorageErrorCode(error) === 'NoSuchBucket') {
throw new plugins.typedrequest.TypedResponseError('Bucket not found');
}
throw error;
}
await this.opsServerRef.objectStorageRef.policyManager.onBucketDeleted(
dataArg.bucketName,
);
await this.opsServerRef.objectStorageRef.auditLogger.log({
actorUserId: dataArg.identity.userId,
action: 'bucket.delete',
targetType: 'bucket',
targetId: dataArg.bucketName,
success: true,
});
return { ok: true };
},
),
@@ -54,8 +96,16 @@ export class BucketsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetBucketPolicy>(
'getBucketPolicy',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
const policy = await this.opsServerRef.objectStorageRef.getBucketPolicy(dataArg.bucketName);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
let policy: string | null;
try {
policy = await this.opsServerRef.objectStorageRef.getBucketPolicy(dataArg.bucketName);
} catch (error) {
if (getStorageErrorCode(error) === 'NoSuchBucket') {
throw new plugins.typedrequest.TypedResponseError('Bucket not found');
}
throw error;
}
return { policy };
},
),
@@ -66,14 +116,24 @@ export class BucketsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PutBucketPolicy>(
'putBucketPolicy',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
// Validate JSON
try {
JSON.parse(dataArg.policy);
} catch {
throw new Error('Invalid JSON policy document');
throw new plugins.typedrequest.TypedResponseError('Invalid JSON policy document');
}
try {
await this.opsServerRef.objectStorageRef.putBucketPolicy(
dataArg.bucketName,
dataArg.policy,
);
} catch (error) {
if (getStorageErrorCode(error) === 'NoSuchBucket') {
throw new plugins.typedrequest.TypedResponseError('Bucket not found');
}
throw error;
}
await this.opsServerRef.objectStorageRef.putBucketPolicy(dataArg.bucketName, dataArg.policy);
return { ok: true };
},
),
@@ -84,8 +144,15 @@ export class BucketsHandler {
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteBucketPolicy>(
'deleteBucketPolicy',
async (dataArg) => {
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
await this.opsServerRef.objectStorageRef.deleteBucketPolicy(dataArg.bucketName);
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
try {
await this.opsServerRef.objectStorageRef.deleteBucketPolicy(dataArg.bucketName);
} catch (error) {
if (getStorageErrorCode(error) === 'NoSuchBucket') {
throw new plugins.typedrequest.TypedResponseError('Bucket not found');
}
throw error;
}
return { ok: true };
},
),