KeyHelp: Panel-Passwort neu vergeben und verschlüsselt hinterlegen (verblurrt wie Lizenzschlüssel)
This commit is contained in:
parent
3a2864ee76
commit
6fec6277f5
9 changed files with 136 additions and 20 deletions
|
|
@ -70,8 +70,10 @@ async function upsert(instanceId: string, r: NormalizedResource): Promise<string
|
|||
return (await one('SELECT id FROM resources WHERE instance_id = ? AND external_ref = ?', [instanceId, r.externalRef]))!.id as string;
|
||||
}
|
||||
|
||||
export interface ExecutePayload { resourceId: string; action: ActionName; params?: Record<string, unknown>; actorUserId: string | null; destructive?: boolean }
|
||||
/** Führt eine Aktion aus. Aufgerufen vom Worker im Rahmen eines persistenten Auftrags; jobId dient als Idempotenzschlüssel. */
|
||||
export interface ExecutePayload { resourceId: string; action: ActionName; params?: Record<string, unknown>; secretEnc?: string; actorUserId: string | null; destructive?: boolean }
|
||||
/** Führt eine Aktion aus. Aufgerufen vom Worker im Rahmen eines persistenten Auftrags; jobId dient als Idempotenzschlüssel.
|
||||
* `secretEnc` (z. B. ein neu erzeugtes Panel-Passwort) steht im Auftrag nur verschlüsselt und wird erst hier entschlüsselt;
|
||||
* nach erfolgreichem "reset_password" wird der Wert erneut verschlüsselt in panel_credentials abgelegt (nie im Klartext, nie im Protokoll). */
|
||||
export async function executeAction(p: ExecutePayload, jobId: string, correlationId: string): Promise<string> {
|
||||
const r = await one('SELECT * FROM resources WHERE id = ?', [p.resourceId]);
|
||||
if (!r) throw new JobFailure('Ressource nicht gefunden', false, 'failed');
|
||||
|
|
@ -79,9 +81,14 @@ export async function executeAction(p: ExecutePayload, jobId: string, correlatio
|
|||
const caps = await connector.capabilities(ctx);
|
||||
if (!caps.includes(ACTION_CAPABILITY[p.action] as Capability) || !connector.execute) throw new JobFailure('Aktion wird vom Connector nicht unterstützt', false, 'failed');
|
||||
const before = { state: r.state, validUntil: r.valid_until };
|
||||
const secrets = p.secretEnc ? (JSON.parse(decrypt(p.secretEnc)) as Record<string, string>) : undefined;
|
||||
try {
|
||||
const out = await connector.execute(ctx, { action: p.action, externalRef: r.external_ref, params: p.params, idempotencyKey: jobId });
|
||||
const out = await connector.execute(ctx, { action: p.action, externalRef: r.external_ref, params: p.params, secrets, idempotencyKey: jobId });
|
||||
if (out.resource) await upsert(r.instance_id, out.resource);
|
||||
if (p.action === 'reset_password' && secrets?.password) {
|
||||
await run('INSERT INTO panel_credentials (resource_id, secret_enc, set_by, set_at) VALUES (?,?,?,UTC_TIMESTAMP(3)) ON DUPLICATE KEY UPDATE secret_enc = VALUES(secret_enc), set_by = VALUES(set_by), set_at = VALUES(set_at)',
|
||||
[p.resourceId, encrypt(secrets.password), p.actorUserId]);
|
||||
}
|
||||
const after = await one('SELECT state, valid_until FROM resources WHERE id = ?', [p.resourceId]);
|
||||
await audit({ actorType: p.actorUserId ? 'user' : 'system', actorId: p.actorUserId, orgId: r.org_id, action: `resource.${p.action}`, resourceType: 'resource', resourceId: p.resourceId, connector: inst.connector_key, correlationId, before, after: { state: after?.state, validUntil: after?.valid_until, params: p.params } });
|
||||
return `${p.action}: ${after?.state ?? 'ok'}`;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue