Add CapabilityGuard infrastructure to enforce capability-based authorization on federation endpoints. Implements fail-closed security model. Security properties: - Deny by default (no capability = deny) - Only explicit true values grant access - Connection must exist and be ACTIVE - All denials logged for audit trail Implementation: - Created CapabilityGuard with fail-closed authorization logic - Added @RequireCapability decorator for marking endpoints - Added getConnectionById() to ConnectionService - Added logCapabilityDenied() to AuditService - 12 comprehensive tests covering all security scenarios Quality gates: - ✅ Tests: 12/12 passing - ✅ Lint: 0 new errors (33 pre-existing) - ✅ TypeScript: 0 new errors (8 pre-existing) Refs #273 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
146 lines
3.6 KiB
TypeScript
146 lines
3.6 KiB
TypeScript
/**
|
|
* Federation Audit Service
|
|
*
|
|
* Logs security-sensitive operations for compliance and monitoring.
|
|
* Uses application logger since ActivityLog requires workspace context.
|
|
*/
|
|
|
|
import { Injectable, Logger } from "@nestjs/common";
|
|
|
|
@Injectable()
|
|
export class FederationAuditService {
|
|
private readonly logger = new Logger(FederationAuditService.name);
|
|
|
|
/**
|
|
* Log instance keypair regeneration (system-level operation)
|
|
* Logged to application logs for security audit trail
|
|
*/
|
|
logKeypairRegeneration(userId: string, instanceId: string): void {
|
|
this.logger.warn({
|
|
event: "FEDERATION_KEYPAIR_REGENERATED",
|
|
userId,
|
|
instanceId,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log instance configuration update (system-level operation)
|
|
* Logged to application logs for security audit trail
|
|
*/
|
|
logInstanceConfigurationUpdate(
|
|
userId: string,
|
|
instanceId: string,
|
|
updates: Record<string, unknown>
|
|
): void {
|
|
this.logger.log({
|
|
event: "FEDERATION_INSTANCE_CONFIG_UPDATED",
|
|
userId,
|
|
instanceId,
|
|
updates,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log federated authentication initiation
|
|
*/
|
|
logFederatedAuthInitiation(userId: string, remoteInstanceId: string): void {
|
|
this.logger.log({
|
|
event: "FEDERATION_AUTH_INITIATED",
|
|
userId,
|
|
remoteInstanceId,
|
|
timestamp: new Date().toISOString(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log federated identity linking
|
|
*/
|
|
logFederatedIdentityLinked(userId: string, remoteInstanceId: string): void {
|
|
this.logger.log({
|
|
event: "FEDERATION_IDENTITY_LINKED",
|
|
userId,
|
|
remoteInstanceId,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log federated identity revocation
|
|
*/
|
|
logFederatedIdentityRevoked(userId: string, remoteInstanceId: string): void {
|
|
this.logger.warn({
|
|
event: "FEDERATION_IDENTITY_REVOKED",
|
|
userId,
|
|
remoteInstanceId,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log identity verification attempt
|
|
*/
|
|
logIdentityVerification(userId: string, remoteInstanceId: string, success: boolean): void {
|
|
const level = success ? "log" : "warn";
|
|
this.logger[level]({
|
|
event: "FEDERATION_IDENTITY_VERIFIED",
|
|
userId,
|
|
remoteInstanceId,
|
|
success,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log identity linking (create mapping)
|
|
*/
|
|
logIdentityLinking(localUserId: string, remoteInstanceId: string, remoteUserId: string): void {
|
|
this.logger.log({
|
|
event: "FEDERATION_IDENTITY_LINKED",
|
|
localUserId,
|
|
remoteUserId,
|
|
remoteInstanceId,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log identity revocation (remove mapping)
|
|
*/
|
|
logIdentityRevocation(localUserId: string, remoteInstanceId: string): void {
|
|
this.logger.warn({
|
|
event: "FEDERATION_IDENTITY_REVOKED",
|
|
localUserId,
|
|
remoteInstanceId,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Log capability denial (security event)
|
|
* Logged when remote instance attempts operation without required capability
|
|
*/
|
|
logCapabilityDenied(
|
|
remoteInstanceId: string,
|
|
requiredCapability: string,
|
|
requestedUrl: string
|
|
): void {
|
|
this.logger.warn({
|
|
event: "FEDERATION_CAPABILITY_DENIED",
|
|
remoteInstanceId,
|
|
requiredCapability,
|
|
requestedUrl,
|
|
timestamp: new Date().toISOString(),
|
|
securityEvent: true,
|
|
});
|
|
}
|
|
}
|