Add provider credential revocation
This commit is contained in:
1 parent
203a48060e
commit
9e44cbb31b
9 files changed
+128
-1
No files matched your search
@@ -28,6 +28,12 @@ export interface ProviderAuthProfileRef {
|
||||
displayHint: string;
|
||||
}
|
||||
|
||||
export interface RevokeProviderAuthProfileInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
}
|
||||
|
||||
export class AuthBrokerService {
|
||||
private readonly audit: AuditService;
|
||||
|
||||
@@ -118,6 +124,33 @@ export class AuthBrokerService {
|
||||
if (!row) throw new Error("Provider credential was not found.");
|
||||
return this.vault.decryptSecret(Buffer.from(row.ciphertext));
|
||||
}
|
||||
|
||||
revokeProviderProfile(input: RevokeProviderAuthProfileInput): void {
|
||||
const row = this.db.prepare(`
|
||||
select id, credential_id
|
||||
from provider_auth_profiles
|
||||
where org_id = ?
|
||||
and provider_id = ?
|
||||
and provider_key = ?
|
||||
and active = 1
|
||||
`).get(input.orgId, input.providerId, input.providerKey) as { id: string; credential_id: string } | undefined;
|
||||
if (!row) throw new Error("Provider credential was not found.");
|
||||
this.db.prepare("update provider_auth_profiles set active = 0 where id = ? and org_id = ?")
|
||||
.run(row.id, input.orgId);
|
||||
this.audit.record({
|
||||
orgId: input.orgId,
|
||||
entityType: "provider_auth_profile",
|
||||
entityId: row.id,
|
||||
actorType: "system",
|
||||
actorId: null,
|
||||
action: "revoked",
|
||||
payload: {
|
||||
providerId: input.providerId,
|
||||
providerKey: input.providerKey,
|
||||
credentialId: row.credential_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function credentialDisplayHint(secret: string): string {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import { createHash } from "node:crypto";
|
||||
import { BrowserWindow, session } from "electron";
|
||||
import type { CreateProviderResponseInput, SaveProviderCredentialInput, UpdateProviderPolicyInput } from "../../shared/commands";
|
||||
import type { CreateProviderResponseInput, RevokeProviderCredentialInput, SaveProviderCredentialInput, UpdateProviderPolicyInput } from "../../shared/commands";
|
||||
import { FEATURE_FLAG_KEY, PROVIDER_AUTH_TYPE, PROVIDER_DATA_POLICY, PROVIDER_EXECUTION_MODE, PROVIDER_REQUEST_STATE, SLO_SIGNAL_KEY, type ProviderAuthType, type ProviderExecutionMode } from "../../shared/domain";
|
||||
import { PROVIDER_CATALOG } from "../../shared/provider-catalog";
|
||||
import { currentProviderUsageWindow } from "../../shared/provider-runtime-domain";
|
||||
@@ -13,6 +13,7 @@ import { SecretVault } from "./secret-vault";
|
||||
import { providerAdapters, type ProviderAdapterRegistry } from "./provider-adapters";
|
||||
|
||||
const AUTH_STATE_CONFIGURED = "configured";
|
||||
const AUTH_STATE_REVOKED = "revoked";
|
||||
const HEALTH_STATE_HEALTHY = "healthy";
|
||||
const HEALTH_STATE_FAILED = "failed";
|
||||
const HEALTH_STATE_UNCHECKED = "unchecked";
|
||||
@@ -69,6 +70,34 @@ export class ProviderService {
|
||||
});
|
||||
}
|
||||
|
||||
revokeCredential(input: RevokeProviderCredentialInput): void {
|
||||
const provider = this.db.prepare(`
|
||||
select id, provider_key
|
||||
from providers
|
||||
where id = ? and org_id = ?
|
||||
`).get(input.providerId, input.orgId) as { id: string; provider_key: string } | undefined;
|
||||
if (!provider) throw new Error("Provider was not found.");
|
||||
this.authBroker.revokeProviderProfile({
|
||||
orgId: input.orgId,
|
||||
providerId: input.providerId,
|
||||
providerKey: provider.provider_key,
|
||||
});
|
||||
this.db.prepare(`
|
||||
update providers
|
||||
set credential_id = null, enabled = 0, auth_state = ?, health_state = ?, last_error = null, last_checked_at = null
|
||||
where id = ? and org_id = ?
|
||||
`).run(AUTH_STATE_REVOKED, HEALTH_STATE_UNCHECKED, input.providerId, input.orgId);
|
||||
this.audit.record({
|
||||
orgId: input.orgId,
|
||||
entityType: "provider",
|
||||
entityId: input.providerId,
|
||||
actorType: "system",
|
||||
actorId: null,
|
||||
action: "credential_revoked",
|
||||
payload: { providerKey: provider.provider_key },
|
||||
});
|
||||
}
|
||||
|
||||
async checkHealth(orgId: string, providerId: string): Promise<void> {
|
||||
const provider = this.loadConfiguredProvider(orgId, providerId);
|
||||
const adapter = this.requireAdapter(provider.provider_key, provider.auth_type);
|
||||
|
||||
Reference in new issue
Block a user