feat: SOC2 audit log completeness — hybrid interceptor + explicit calls
Add AuditInterceptor as a safety net that auto-audits any POST/PUT/DELETE without an explicit audit call (excludes data ingestion + heartbeat). AuditService sets a request attribute so the interceptor skips when explicit logging already happened. New explicit audit calls: - ApplicationConfigController: view/update app config - AgentCommandController: send/broadcast commands (AGENT category) - AgentRegistrationController: agent register + token refresh - UiAuthController: UI token refresh - OidcAuthController: OIDC callback failure - AuditLogController: view audit log (sensitive read) - UserAdminController: view users (sensitive read) - OidcConfigAdminController: view OIDC config (sensitive read) New AuditCategory.AGENT added. Frontend audit log filter updated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,9 @@ public class OidcAuthController {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("OIDC callback failed: {}", e.getMessage(), e);
|
||||
auditService.log("unknown", "login_oidc", AuditCategory.AUTH, null,
|
||||
Map.of("reason", e.getMessage() != null ? e.getMessage() : "unknown"),
|
||||
AuditResult.FAILURE, httpRequest);
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED,
|
||||
"OIDC authentication failed: " + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -123,7 +123,8 @@ public class UiAuthController {
|
||||
@ApiResponse(responseCode = "200", description = "Token refreshed")
|
||||
@ApiResponse(responseCode = "401", description = "Invalid refresh token",
|
||||
content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
|
||||
public ResponseEntity<AuthTokenResponse> refresh(@RequestBody RefreshRequest request) {
|
||||
public ResponseEntity<AuthTokenResponse> refresh(@RequestBody RefreshRequest request,
|
||||
HttpServletRequest httpRequest) {
|
||||
try {
|
||||
JwtValidationResult result = jwtService.validateRefreshToken(request.refreshToken());
|
||||
if (!result.subject().startsWith("user:")) {
|
||||
@@ -138,6 +139,7 @@ public class UiAuthController {
|
||||
String displayName = userRepository.findById(result.subject())
|
||||
.map(UserInfo::displayName)
|
||||
.orElse(result.subject());
|
||||
auditService.log(result.subject(), "token_refresh", AuditCategory.AUTH, null, null, AuditResult.SUCCESS, httpRequest);
|
||||
return ResponseEntity.ok(new AuthTokenResponse(accessToken, refreshToken, displayName, null));
|
||||
} catch (ResponseStatusException e) {
|
||||
throw e;
|
||||
|
||||
Reference in New Issue
Block a user