feat(managed-secrets): add centrally managed secrets with GITOPS_ prefix pushed to multiple targets
Introduce managed secrets owned by GitOps that can be defined once and
pushed to any combination of projects/groups across connections. Values
are stored in OS keychain, secrets appear on targets as GITOPS_{key}.
This commit is contained in:
158
ts/opsserver/handlers/managedsecrets.handler.ts
Normal file
158
ts/opsserver/handlers/managedsecrets.handler.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
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';
|
||||
|
||||
export class ManagedSecretsHandler {
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
constructor(private opsServerRef: OpsServer) {
|
||||
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
private get actionLog() {
|
||||
return this.opsServerRef.gitopsAppRef.actionLog;
|
||||
}
|
||||
|
||||
private get manager() {
|
||||
return this.opsServerRef.gitopsAppRef.managedSecretsManager;
|
||||
}
|
||||
|
||||
private registerHandlers(): void {
|
||||
// List all managed secrets
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetManagedSecrets>(
|
||||
'getManagedSecrets',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const managedSecrets = await this.manager.getAll();
|
||||
return { managedSecrets };
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Get single managed secret
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetManagedSecret>(
|
||||
'getManagedSecret',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const managedSecret = await this.manager.getById(dataArg.managedSecretId);
|
||||
if (!managedSecret) throw new Error(`Managed secret not found: ${dataArg.managedSecretId}`);
|
||||
return { managedSecret };
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Create managed secret
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateManagedSecret>(
|
||||
'createManagedSecret',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const result = await this.manager.create(
|
||||
dataArg.key,
|
||||
dataArg.value,
|
||||
dataArg.description,
|
||||
dataArg.targets,
|
||||
);
|
||||
this.actionLog.append({
|
||||
actionType: 'create',
|
||||
entityType: 'managed-secret',
|
||||
entityId: result.managedSecret.id,
|
||||
entityName: `GITOPS_${dataArg.key}`,
|
||||
details: `Created managed secret "${dataArg.key}" with ${dataArg.targets.length} target(s)`,
|
||||
username: dataArg.identity.username,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Update managed secret
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateManagedSecret>(
|
||||
'updateManagedSecret',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const result = await this.manager.update(dataArg.managedSecretId, {
|
||||
value: dataArg.value,
|
||||
description: dataArg.description,
|
||||
targets: dataArg.targets,
|
||||
});
|
||||
this.actionLog.append({
|
||||
actionType: 'update',
|
||||
entityType: 'managed-secret',
|
||||
entityId: dataArg.managedSecretId,
|
||||
entityName: `GITOPS_${result.managedSecret.key}`,
|
||||
details: `Updated managed secret "${result.managedSecret.key}"`,
|
||||
username: dataArg.identity.username,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Delete managed secret
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteManagedSecret>(
|
||||
'deleteManagedSecret',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const secret = await this.manager.getById(dataArg.managedSecretId);
|
||||
const result = await this.manager.delete(dataArg.managedSecretId);
|
||||
this.actionLog.append({
|
||||
actionType: 'delete',
|
||||
entityType: 'managed-secret',
|
||||
entityId: dataArg.managedSecretId,
|
||||
entityName: secret ? `GITOPS_${secret.key}` : dataArg.managedSecretId,
|
||||
details: `Deleted managed secret${secret ? ` "${secret.key}"` : ''}`,
|
||||
username: dataArg.identity.username,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Push single managed secret
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushManagedSecret>(
|
||||
'pushManagedSecret',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const result = await this.manager.pushOne(dataArg.managedSecretId);
|
||||
this.actionLog.append({
|
||||
actionType: 'push',
|
||||
entityType: 'managed-secret',
|
||||
entityId: dataArg.managedSecretId,
|
||||
entityName: `GITOPS_${result.managedSecret.key}`,
|
||||
details: `Pushed managed secret "${result.managedSecret.key}" to ${result.pushResults.length} target(s)`,
|
||||
username: dataArg.identity.username,
|
||||
});
|
||||
return result;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Push all managed secrets
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushAllManagedSecrets>(
|
||||
'pushAllManagedSecrets',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
||||
const results = await this.manager.pushAll();
|
||||
this.actionLog.append({
|
||||
actionType: 'push',
|
||||
entityType: 'managed-secret',
|
||||
entityId: 'all',
|
||||
entityName: 'All managed secrets',
|
||||
details: `Pushed ${results.length} managed secret(s) to their targets`,
|
||||
username: dataArg.identity.username,
|
||||
});
|
||||
return { results };
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user