From 74a9eba8196f9b8d55770e70e260935259afafe9 Mon Sep 17 00:00:00 2001 From: shrihari7396 Date: Sat, 4 Apr 2026 14:38:54 +0530 Subject: [PATCH 1/4] Repairing Started From Here ... --- .codex | 0 .../java/edu/pict/dtos/BehaviorLogEvent.java | 26 ++ .../events/DefaultGatewayEventFactory.java | 50 ++++ .../DefaultRequestContextExtractor.java | 46 ++++ .../events/GatewayEventFactory.java | 11 + .../apigateway/events/RequestContext.java | 13 + .../events/RequestContextExtractor.java | 8 + .../security/RouteAccessPolicy.java | 10 + .../security/StaticRouteAccessPolicy.java | 26 ++ FIX_IMPLEMENTATION_TRACKER.md | 103 ++++++++ .../grpc/UserLogEventGrpcService.java | 63 +++++ .../src/main/proto/user_log_event.proto | 34 +++ .../pict/mcpservice/config/AsyncConfig.java | 26 ++ .../mcpservice/ports/AnomalyScoringPort.java | 9 + .../pict/mcpservice/ports/BlockEnforcer.java | 10 + .../mcpservice/ports/HistoryProvider.java | 9 + .../service/AsyncThreatEvaluator.java | 36 +++ .../blocking/AsyncThreatStrategy.java | 4 + SYSTEM_REMEDIATION_PLAN_SOLID.md | 230 ++++++++++++++++++ 19 files changed, 714 insertions(+) create mode 100644 .codex create mode 100644 AIService/src/main/java/edu/pict/dtos/BehaviorLogEvent.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultGatewayEventFactory.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultRequestContextExtractor.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/events/GatewayEventFactory.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContext.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContextExtractor.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/security/RouteAccessPolicy.java create mode 100644 ApiGateway/src/main/java/edu/pict/apigateway/security/StaticRouteAccessPolicy.java create mode 100644 FIX_IMPLEMENTATION_TRACKER.md create mode 100644 LogingService/src/main/java/edu/pict/loggingservice/grpc/UserLogEventGrpcService.java create mode 100644 LogingService/src/main/proto/user_log_event.proto create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/config/AsyncConfig.java create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/ports/AnomalyScoringPort.java create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/ports/BlockEnforcer.java create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/ports/HistoryProvider.java create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/service/AsyncThreatEvaluator.java create mode 100644 MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AsyncThreatStrategy.java create mode 100644 SYSTEM_REMEDIATION_PLAN_SOLID.md diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/AIService/src/main/java/edu/pict/dtos/BehaviorLogEvent.java b/AIService/src/main/java/edu/pict/dtos/BehaviorLogEvent.java new file mode 100644 index 0000000..71c64bf --- /dev/null +++ b/AIService/src/main/java/edu/pict/dtos/BehaviorLogEvent.java @@ -0,0 +1,26 @@ +package edu.pict.dtos; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BehaviorLogEvent { + private String uuid; + private String path; + private String method; + private String routeId; + private String decision; + private long latencyMs; + private String queryParams; + private String clientIp; + private int statusCode; + private long requestSize; + private long timestamp; + private String userAgent; +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultGatewayEventFactory.java b/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultGatewayEventFactory.java new file mode 100644 index 0000000..b9d0bd8 --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultGatewayEventFactory.java @@ -0,0 +1,50 @@ +package edu.pict.apigateway.events; + +import edu.pict.apigateway.kafkaEvent.LogEvent; +import edu.pict.apigateway.kafkaEvent.SecurityAlertEvent; +import org.springframework.stereotype.Component; + +@Component +public class DefaultGatewayEventFactory implements GatewayEventFactory { + + @Override + public LogEvent buildLogEvent(RequestContext context, int statusCode, long latencyMs) { + return LogEvent.builder() + .uuid(context.uuid()) + .path(context.path()) + .method(context.method()) + .routeId(context.routeId()) + .decision("ALLOWED") + .latencyMs(latencyMs) + .queryParams(context.queryParams()) + .clientIp(context.clientIp()) + .statusCode(statusCode) + .requestSize(context.requestSize()) + .timestamp(context.timestamp()) + .userAgent(context.userAgent()) + .build(); + } + + @Override + public SecurityAlertEvent buildSecurityAlert( + RequestContext context, int statusCode, String reasonPhrase) { + return SecurityAlertEvent.builder() + .uuid(context.uuid()) + .errorCode(statusCode) + .reason(reasonPhrase) + .attemptedPath(context.path()) + .method(context.method()) + .userAgent(context.userAgent()) + .clientIp(context.clientIp()) + .alertSeverity(determineSeverity(statusCode)) + .timestamp(context.timestamp()) + .build(); + } + + private String determineSeverity(int code) { + if (code >= 500) return "HIGH"; + if (code == 429 || code == 403 || code == 401) return "MEDIUM"; + return "LOW"; + } +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultRequestContextExtractor.java b/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultRequestContextExtractor.java new file mode 100644 index 0000000..a4d68b7 --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultRequestContextExtractor.java @@ -0,0 +1,46 @@ +package edu.pict.apigateway.events; + +import edu.pict.apigateway.service.IpService; +import edu.pict.apigateway.util.Constants; +import lombok.RequiredArgsConstructor; +import org.springframework.cloud.gateway.route.Route; +import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; + +@Component +@RequiredArgsConstructor +public class DefaultRequestContextExtractor implements RequestContextExtractor { + + private final IpService ipService; + + @Override + public RequestContext extract(ServerWebExchange exchange) { + String uuid = exchange.getRequest().getHeaders().getFirst(Constants.VISITOR_ID); + String path = exchange.getRequest().getURI().getPath(); + String method = exchange.getRequest().getMethod().toString(); + String queryParams = exchange.getRequest().getQueryParams().toString(); + long requestSize = exchange.getRequest().getHeaders().getContentLength(); + String userAgent = exchange.getRequest().getHeaders().getFirst("User-Agent"); + String remoteAddress = + exchange.getRequest().getRemoteAddress() != null + ? exchange.getRequest().getRemoteAddress().getAddress().getHostAddress() + : null; + String clientIp = ipService.resolveClientIp(exchange.getRequest().getHeaders(), remoteAddress); + + Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); + String routeId = (route != null) ? route.getId() : "unknown"; + + return new RequestContext( + uuid, + path, + method, + routeId, + queryParams, + Math.max(requestSize, 0), + clientIp, + userAgent, + System.currentTimeMillis()); + } +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/events/GatewayEventFactory.java b/ApiGateway/src/main/java/edu/pict/apigateway/events/GatewayEventFactory.java new file mode 100644 index 0000000..f85d8cf --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/events/GatewayEventFactory.java @@ -0,0 +1,11 @@ +package edu.pict.apigateway.events; + +import edu.pict.apigateway.kafkaEvent.LogEvent; +import edu.pict.apigateway.kafkaEvent.SecurityAlertEvent; + +public interface GatewayEventFactory { + LogEvent buildLogEvent(RequestContext context, int statusCode, long latencyMs); + + SecurityAlertEvent buildSecurityAlert(RequestContext context, int statusCode, String reasonPhrase); +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContext.java b/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContext.java new file mode 100644 index 0000000..0651e62 --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContext.java @@ -0,0 +1,13 @@ +package edu.pict.apigateway.events; + +public record RequestContext( + String uuid, + String path, + String method, + String routeId, + String queryParams, + long requestSize, + String clientIp, + String userAgent, + long timestamp) {} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContextExtractor.java b/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContextExtractor.java new file mode 100644 index 0000000..d4a88fe --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContextExtractor.java @@ -0,0 +1,8 @@ +package edu.pict.apigateway.events; + +import org.springframework.web.server.ServerWebExchange; + +public interface RequestContextExtractor { + RequestContext extract(ServerWebExchange exchange); +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/security/RouteAccessPolicy.java b/ApiGateway/src/main/java/edu/pict/apigateway/security/RouteAccessPolicy.java new file mode 100644 index 0000000..cb828f3 --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/security/RouteAccessPolicy.java @@ -0,0 +1,10 @@ +package edu.pict.apigateway.security; + +public interface RouteAccessPolicy { + boolean isPublicPath(String path); + + default boolean requiresAuthentication(String path) { + return !isPublicPath(path); + } +} + diff --git a/ApiGateway/src/main/java/edu/pict/apigateway/security/StaticRouteAccessPolicy.java b/ApiGateway/src/main/java/edu/pict/apigateway/security/StaticRouteAccessPolicy.java new file mode 100644 index 0000000..24d6521 --- /dev/null +++ b/ApiGateway/src/main/java/edu/pict/apigateway/security/StaticRouteAccessPolicy.java @@ -0,0 +1,26 @@ +package edu.pict.apigateway.security; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; + +@Component +@RequiredArgsConstructor +public class StaticRouteAccessPolicy implements RouteAccessPolicy { + + private static final List PUBLIC_PATTERNS = + List.of( + "/api/auth/**", + "/actuator/health", + "/actuator/info", + "/favicon.ico"); + + private final AntPathMatcher pathMatcher = new AntPathMatcher(); + + @Override + public boolean isPublicPath(String path) { + return PUBLIC_PATTERNS.stream().anyMatch(pattern -> pathMatcher.match(pattern, path)); + } +} + diff --git a/FIX_IMPLEMENTATION_TRACKER.md b/FIX_IMPLEMENTATION_TRACKER.md new file mode 100644 index 0000000..b859ed0 --- /dev/null +++ b/FIX_IMPLEMENTATION_TRACKER.md @@ -0,0 +1,103 @@ +# SentientGate Fix Implementation Tracker + +Date: 2026-04-04 +Status: Phase 0 + significant Phase 1/2/3/4 changes implemented. + +## Implemented Changes + +1. Secret and repository hardening +- Removed leaked key: `private_key.pem` +- Removed backup config with secrets: `ApiGateway/src/main/resources/application.yml.bak` +- Externalized secrets: + - `ApiGateway/src/main/resources/application.yml` + - `LogingService/src/main/resources/application.yml` + - `docker-compose.yml` +- Hardened ignore rules in `.gitignore` (`*.pem`, `.env*`, build and IDE folders) + +2. Gateway design-pattern refactor and security controls +- Added policy pattern: + - `ApiGateway/src/main/java/edu/pict/apigateway/security/RouteAccessPolicy.java` + - `ApiGateway/src/main/java/edu/pict/apigateway/security/StaticRouteAccessPolicy.java` +- Added factory/extractor pattern for event creation: + - `ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContext.java` + - `ApiGateway/src/main/java/edu/pict/apigateway/events/RequestContextExtractor.java` + - `ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultRequestContextExtractor.java` + - `ApiGateway/src/main/java/edu/pict/apigateway/events/GatewayEventFactory.java` + - `ApiGateway/src/main/java/edu/pict/apigateway/events/DefaultGatewayEventFactory.java` +- Updated filters: + - `JwtExtractionFilter`: JWT required on protected routes + - `SentientGateFilter`: removed `assert`, uses extractor+factory + - `BlacklistFilter`: checks UUID and IP blacklist keys (legacy compatible) +- Improved proxy/IP handling: + - `ApiGateway/src/main/java/edu/pict/apigateway/service/IpService.java` +- Updated blacklist management controller for namespaced UUID keys: + - `ApiGateway/src/main/java/edu/pict/apigateway/controller/ManagementController.java` + +3. MCP pipeline architecture and resilience improvements +- Added dependency inversion ports: + - `MCPService/src/main/java/edu/pict/mcpservice/ports/HistoryProvider.java` + - `MCPService/src/main/java/edu/pict/mcpservice/ports/BlockEnforcer.java` + - `MCPService/src/main/java/edu/pict/mcpservice/ports/AnomalyScoringPort.java` +- Added async strategy segregation: + - `MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AsyncThreatStrategy.java` + - `MCPService/src/main/java/edu/pict/mcpservice/service/AsyncThreatEvaluator.java` + - `MCPService/src/main/java/edu/pict/mcpservice/config/AsyncConfig.java` +- Updated analysis pipeline: + - `MCPService/src/main/java/edu/pict/mcpservice/service/McpAnalysisService.java` + - Added pre-block check, dedup window, sync/async strategy split +- Added Caffeine history cache + gRPC deadline: + - `MCPService/src/main/java/edu/pict/mcpservice/service/EventHistoryService.java` + - `MCPService/build.gradle` +- Improved enforcement serialization and key strategy: + - `MCPService/src/main/java/edu/pict/mcpservice/service/EnforcementService.java` + - Stores JSON metadata and writes UUID/IP blacklist keys +- Improved pattern matching coverage: + - `MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/PatternMatchStrategy.java` +- Batch listener behavior aligned: + - `MCPService/src/main/java/edu/pict/mcpservice/kafkaListeners/SecurityEventListners.java` +- Feign endpoint correction and timeout config: + - `MCPService/src/main/java/edu/pict/mcpservice/clients/AiServiceFeignClient.java` + - `MCPService/src/main/resources/application.yml` + +4. Logging service correctness and performance +- Added gRPC server implementation: + - `LogingService/src/main/proto/user_log_event.proto` + - `LogingService/src/main/java/edu/pict/loggingservice/grpc/UserLogEventGrpcService.java` + - `LogingService/src/main/java/edu/pict/loggingservice/repository/GatewayLogRepository.java` + - `LogingService/src/main/resources/application.yml` + - `LogingService/build.gradle` +- Replaced `parallelStream()` with `stream()`: + - `LogingService/src/main/java/edu/pict/loggingservice/service/KafkaBatchService.java` +- Added DB indexes on hot query paths: + - `LogingService/src/main/java/edu/pict/loggingservice/entity/GatewayLogEntity.java` +- Hardened Kafka trusted packages and DDL config: + - `LogingService/src/main/resources/application.yml` + +5. AI request-contract compatibility and prompt-injection hardening +- Added history-compatible event DTO: + - `AIService/src/main/java/edu/pict/dtos/BehaviorLogEvent.java` +- Extended request DTO for MCP payload shape: + - `AIService/src/main/java/edu/pict/dtos/AnomalyDetectionRequest.java` +- Added feature derivation and route-sensitivity sanitization: + - `AIService/src/main/java/edu/pict/service/AnomalyDetectionService.java` +- Added response aliasing support in MCP consumer: + - `MCPService/src/main/java/edu/pict/mcpservice/model/AnomalyDetectionResponse.java` + +## Verification Notes + +Automated test runs in this execution environment were blocked by runtime/toolchain mismatch: +- Maven builds require Java 21 `--release`, but runner JDK is older. +- Gradle plugin resolution requires Java 17+, runner JDK is Java 11. + +Commands attempted: +- `ApiGateway: ./mvnw -Dmaven.repo.local=/tmp/.m2-api test` +- `AIService: ./mvnw -Dmaven.repo.local=/tmp/.m2-ai test` +- `MCPService: GRADLE_USER_HOME=/tmp/.gradle-mcp ./gradlew test` +- `LogingService: GRADLE_USER_HOME=/tmp/.gradle-log ./gradlew test` + +## Remaining Planned Items + +- Integrate Spring Security authorization chain with JWT-authenticated principal (beyond header-level enforcement). +- Add circuit breaker policy (`Resilience4j`) around gRPC + AI calls. +- Add dashboard cache layer for aggregate queries. +- Add environment profile split for strict production defaults (`ddl-auto=validate`, TLS, service auth). diff --git a/LogingService/src/main/java/edu/pict/loggingservice/grpc/UserLogEventGrpcService.java b/LogingService/src/main/java/edu/pict/loggingservice/grpc/UserLogEventGrpcService.java new file mode 100644 index 0000000..53412c1 --- /dev/null +++ b/LogingService/src/main/java/edu/pict/loggingservice/grpc/UserLogEventGrpcService.java @@ -0,0 +1,63 @@ +package edu.pict.loggingservice.grpc; + +import edu.pict.loggingservice.entity.GatewayLogEntity; +import edu.pict.loggingservice.repository.GatewayLogRepository; +import edu.pict.mcpservice.grpc.UserLogEvent; +import edu.pict.mcpservice.grpc.UserLogEventResponse; +import edu.pict.mcpservice.grpc.UserLogEventServiceGrpc; +import edu.pict.mcpservice.grpc.UserLogEventsRequest; +import io.grpc.stub.StreamObserver; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.devh.boot.grpc.server.service.GrpcService; + +@GrpcService +@RequiredArgsConstructor +@Slf4j +public class UserLogEventGrpcService extends UserLogEventServiceGrpc.UserLogEventServiceImplBase { + + private final GatewayLogRepository repository; + + @Override + public void getUserEvents( + UserLogEventsRequest request, StreamObserver responseObserver) { + try { + int durationMinutes = request.getDuration() <= 0 ? 10 : request.getDuration(); + Instant since = Instant.now().minus(Duration.ofMinutes(durationMinutes)); + + List logs = + repository.findByVisitorIdAndOccurredAtAfter(request.getUuid(), since); + + List protoEvents = logs.stream().map(this::toProto).toList(); + responseObserver.onNext( + UserLogEventResponse.newBuilder().addAllUserLogEvents(protoEvents).build()); + responseObserver.onCompleted(); + } catch (Exception e) { + log.error("Failed to fetch gRPC user events for UUID {}", request.getUuid(), e); + responseObserver.onError(e); + } + } + + private UserLogEvent toProto(GatewayLogEntity entity) { + return UserLogEvent.newBuilder() + .setUuid(nullSafe(entity.getVisitorId())) + .setPath(nullSafe(entity.getPath())) + .setMethod(nullSafe(entity.getMethod())) + .setLatencyMs(entity.getLatencyMs()) + .setQueryParams(nullSafe(entity.getQueryParams())) + .setClientIp(nullSafe(entity.getClientIp())) + .setStatusCode(entity.getStatusCode()) + .setRequestSize(entity.getRequestSize()) + .setTimestamp(entity.getOccurredAt().toEpochMilli()) + .setUserAgent(nullSafe(entity.getUserAgent())) + .build(); + } + + private String nullSafe(String value) { + return value == null ? "" : value; + } +} + diff --git a/LogingService/src/main/proto/user_log_event.proto b/LogingService/src/main/proto/user_log_event.proto new file mode 100644 index 0000000..2dbb399 --- /dev/null +++ b/LogingService/src/main/proto/user_log_event.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "edu.pict.mcpservice.grpc"; +option java_outer_classname = "UserLogEventProto"; + +package log; + +message UserLogEvent { + string uuid = 1; + string path = 2; + string method = 3; + int64 latency_ms = 4; + string query_params = 5; + string client_ip = 6; + int32 status_code = 7; + int64 request_size = 8; + int64 timestamp = 9; + string user_agent = 10; +} + +message UserLogEventsRequest { + string uuid = 1; + int32 duration = 2; +} + +message UserLogEventResponse { + repeated UserLogEvent user_log_events = 1; +} + +service UserLogEventService { + rpc GetUserEvents (UserLogEventsRequest) returns (UserLogEventResponse); +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/config/AsyncConfig.java b/MCPService/src/main/java/edu/pict/mcpservice/config/AsyncConfig.java new file mode 100644 index 0000000..910307f --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/config/AsyncConfig.java @@ -0,0 +1,26 @@ +package edu.pict.mcpservice.config; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class AsyncConfig { + + @Bean("aiAnalysisExecutor") + public Executor aiAnalysisExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(20); + executor.setQueueCapacity(500); + executor.setThreadNamePrefix("ai-analysis-"); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/ports/AnomalyScoringPort.java b/MCPService/src/main/java/edu/pict/mcpservice/ports/AnomalyScoringPort.java new file mode 100644 index 0000000..7152ec4 --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/ports/AnomalyScoringPort.java @@ -0,0 +1,9 @@ +package edu.pict.mcpservice.ports; + +import edu.pict.mcpservice.model.AnomalyDetectionRequest; +import edu.pict.mcpservice.model.AnomalyDetectionResponse; + +public interface AnomalyScoringPort { + AnomalyDetectionResponse analyze(AnomalyDetectionRequest request); +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/ports/BlockEnforcer.java b/MCPService/src/main/java/edu/pict/mcpservice/ports/BlockEnforcer.java new file mode 100644 index 0000000..aa7bd4f --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/ports/BlockEnforcer.java @@ -0,0 +1,10 @@ +package edu.pict.mcpservice.ports; + +import edu.pict.mcpservice.stratagies.blocking.ThreatStrategy; + +public interface BlockEnforcer { + boolean isBlocked(String uuid); + + void blockUser(String uuid, String clientIp, ThreatStrategy strategy); +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/ports/HistoryProvider.java b/MCPService/src/main/java/edu/pict/mcpservice/ports/HistoryProvider.java new file mode 100644 index 0000000..1d9458c --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/ports/HistoryProvider.java @@ -0,0 +1,9 @@ +package edu.pict.mcpservice.ports; + +import edu.pict.mcpservice.grpc.UserLogEvent; +import java.util.List; + +public interface HistoryProvider { + List getAllEventsInDuration(String uuid, int duration); +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/service/AsyncThreatEvaluator.java b/MCPService/src/main/java/edu/pict/mcpservice/service/AsyncThreatEvaluator.java new file mode 100644 index 0000000..5aaf35c --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/service/AsyncThreatEvaluator.java @@ -0,0 +1,36 @@ +package edu.pict.mcpservice.service; + +import edu.pict.mcpservice.kafkaEvents.LogEvent; +import edu.pict.mcpservice.kafkaEvents.SecurityAlertEvent; +import edu.pict.mcpservice.ports.BlockEnforcer; +import edu.pict.mcpservice.stratagies.blocking.AsyncThreatStrategy; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@Slf4j +public class AsyncThreatEvaluator { + + private final BlockEnforcer blockEnforcer; + + @Async("aiAnalysisExecutor") + public void evaluate( + SecurityAlertEvent alert, List history, List asyncStrategies) { + if (blockEnforcer.isBlocked(alert.getUuid())) { + log.debug("Skipping async evaluation for already blocked UUID {}", alert.getUuid()); + return; + } + + asyncStrategies.stream() + .filter(strategy -> strategy.isAvailable(alert, history)) + .findFirst() + .ifPresent( + strategy -> + blockEnforcer.blockUser(alert.getUuid(), alert.getClientIp(), strategy)); + } +} + diff --git a/MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AsyncThreatStrategy.java b/MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AsyncThreatStrategy.java new file mode 100644 index 0000000..48f2b48 --- /dev/null +++ b/MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AsyncThreatStrategy.java @@ -0,0 +1,4 @@ +package edu.pict.mcpservice.stratagies.blocking; + +public interface AsyncThreatStrategy extends ThreatStrategy {} + diff --git a/SYSTEM_REMEDIATION_PLAN_SOLID.md b/SYSTEM_REMEDIATION_PLAN_SOLID.md new file mode 100644 index 0000000..b1c955b --- /dev/null +++ b/SYSTEM_REMEDIATION_PLAN_SOLID.md @@ -0,0 +1,230 @@ +# SentientGate Remediation Plan + SOLID Audit + +Date: 2026-04-04 +Scope: Security flaws, architectural flaws, and SOLID-driven refactor plan. + +## 1. Execution Plan (Phased) + +### Phase 0: Immediate Containment (Day 0) +- Rotate and remove leaked key material: + - `/private_key.pem` + - hardcoded secrets in `ApiGateway/src/main/resources/application.yml` +- Move secrets to environment variables for all services. +- Strengthen `.gitignore` for `*.pem`, `.env*`, `target/`, `build/`, `.idea/`, `application*.yml.bak`. +- Remove tracked secret backups like `ApiGateway/src/main/resources/application.yml.bak`. + +Definition of Done: +- No secrets in tracked source. +- App starts with env-based secrets in local/dev profiles. + +### Phase 1: Gateway Security Baseline (Day 1-2) +- Replace `permitAll()` with endpoint-level authorization policy. +- Rework CSRF policy: + - enable for cookie/session browser flows, or + - explicitly disable only for fully stateless token APIs with compensating controls. +- Integrate trusted proxy/IP extraction via `IpService` inside `SentientGateFilter`. +- Replace UUID-only blacklist checks with UUID + IP strategy. +- Remove production `assert` checks and replace with explicit validation/guard clauses. + +Definition of Done: +- Protected internal routes require auth. +- IP extraction is deterministic and proxy-safe. +- Blacklist cannot be bypassed by only rotating UUID cookie. + +### Phase 2: MCP Pipeline Performance + Safety (Day 2-4) +- Add pre-check: skip analysis when already blocked in Redis. +- Add dedup window per UUID/signature for repeated alerts. +- Add short TTL cache for recent history fetches. +- Split strategy execution: + - fast deterministic strategies on consumer thread + - slow AI strategy on async executor. +- Add timeout + circuit breaker for gRPC and AI calls. +- Restrict Kafka `trusted.packages` from `"*"` to explicit packages. + +Definition of Done: +- Under burst traffic, consumer lag remains bounded. +- AI unavailability does not stall Kafka consumers. + +### Phase 3: Service Integration Correctness (Day 4-5) +- Fix AI Feign client name/path mismatch. +- Implement gRPC server in LoggingService for history retrieval. +- Add gRPC deadlines and fallback paths in MCP. + +Definition of Done: +- History-dependent strategies function correctly in integration tests. +- MCP handles LoggingService outage without thread starvation. + +### Phase 4: Logging/Data Hardening (Day 5-6) +- Replace `parallelStream()` with `stream()` in ingestion mapping. +- Move `ddl-auto` to safer production profile (`validate`/migration-driven). +- Add DB indexes for dashboard query paths. +- Add short-lived cache for dashboard aggregates. +- Store block metadata as JSON, not `record.toString()`. + +Definition of Done: +- Dashboard load no longer spikes DB repeatedly. +- Block records are machine-readable and auditable. + +### Phase 5: Resilience Baseline (Day 6-7) +- Add profile-level HA guidance for Redis/Kafka/Postgres/service replicas. +- Keep dev-simple profile; add prod-safe profile defaults. + +Definition of Done: +- Clear failover and scaling baseline exists for non-local environments. + +### Phase 6: Verification + Documentation (Day 7) +- Add/expand unit + integration tests for all fixed flaw classes. +- Create fix tracker with: + - flaw ID + - changed files + - tests + - verification commands + - residual risks. + +Definition of Done: +- Each flaw has traceable fix evidence. + +--- + +## 2. SOLID Violation Audit (Current Code) + +## S — Single Responsibility Principle (SRP) + +Break 1: +- File: `ApiGateway/src/main/java/edu/pict/apigateway/filters/global/SentientGateFilter.java` +- Problem: + - same class extracts request metadata, decides alert severity, builds two event models, and publishes to Kafka. +- Fix: + - split into: + - `RequestContextExtractor` + - `LogEventFactory` + - `SecurityAlertFactory` + - `SecurityEventPublisher` + +Break 2: +- File: `MCPService/src/main/java/edu/pict/mcpservice/service/McpAnalysisService.java` +- Problem: + - orchestrates history fetch, transforms data models, executes strategies, and triggers enforcement. +- Fix: + - split orchestration: + - `HistoryProvider` + - `StrategyEvaluator` + - `ThreatDecisionEngine` + - `EnforcementCoordinator` + +Break 3: +- File: `LogingService/src/main/java/edu/pict/loggingservice/service/DashboardStatsService.java` +- Problem: + - handles stats retrieval, error fallback policy, throughput calculation, and p99 logic in one class. +- Fix: + - separate into repository-facing query service + metrics calculation utility + caching facade. + +## O — Open/Closed Principle (OCP) + +Break 1: +- File: `MCPService/src/main/java/edu/pict/mcpservice/service/McpAnalysisService.java` +- Problem: + - transformation from gRPC model to internal model is inlined in service flow; adding alternate history sources forces edits in same class. +- Fix: + - introduce mapper interface and pluggable history source adapters. + +Break 2: +- File: `MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/PatternMatchStrategy.java` +- Problem: + - static embedded malicious patterns mean updates require code changes/redeploy. +- Fix: + - externalize signatures to config/rules provider and keep strategy closed for modification. + +## L — Liskov Substitution Principle (LSP) + +Break 1 (behavioral contract risk): +- File: `MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/AiAnomalyStrategy.java` +- Problem: + - strategy call can block for long periods while other strategies are fast/pure. This violates expected substitutability of `ThreatStrategy` from a caller timing perspective. +- Fix: + - split strategy contracts: + - `SynchronousThreatStrategy` + - `AsynchronousThreatStrategy` + - evaluate each in appropriate execution pipeline. + +## I — Interface Segregation Principle (ISP) + +Break 1: +- File: `MCPService/src/main/java/edu/pict/mcpservice/stratagies/blocking/ThreatStrategy.java` (used by all strategies) +- Problem: + - single contract forces both fast deterministic and slow remote-dependent strategies into same interface behavior. +- Fix: + - segregate into narrower interfaces: + - `RuleBasedThreatStrategy` + - `AiThreatStrategy` + - optional marker for history requirement. + +## D — Dependency Inversion Principle (DIP) + +Break 1: +- File: `MCPService/src/main/java/edu/pict/mcpservice/service/McpAnalysisService.java` +- Problem: + - depends directly on concrete `EventHistoryService` and `EnforcementService`. +- Fix: + - depend on abstractions: + - `HistoryProvider` + - `BlockEnforcer`. + +Break 2: +- File: `MCPService/src/main/java/edu/pict/mcpservice/service/AIClient.java` +- Problem: + - concrete dependence on Feign transport details leaks into domain service behavior. +- Fix: + - introduce `AnomalyScoringPort` interface; Feign/WebClient become infrastructure adapters. + +Break 3: +- File: `ApiGateway/src/main/java/edu/pict/apigateway/config/SecurityConfig.java` +- Problem: + - security policy is hardcoded directly in config class (`anyExchange().permitAll()`), making higher-level policy dependent on low-level implementation. +- Fix: + - model policy in dedicated `AuthorizationPolicy` abstraction and apply through config. + +--- + +## 3. SOLID-Aligned Target Module Structure + +ApiGateway: +- `security.policy` (authorization + CSRF decisions) +- `request.context` (visitor/IP extraction and validation) +- `events.factory` (log/alert event composition) +- `events.publisher` (Kafka transport only) + +MCPService: +- `analysis.core` (decision engine) +- `analysis.strategy.sync` (fast local rules) +- `analysis.strategy.async` (AI/remote rules) +- `analysis.history` (grpc/cache providers) +- `analysis.enforcement` (blocking port + redis adapter) + +LoggingService: +- `ingestion` (Kafka to entity mapping) +- `history.api` (gRPC/REST adapters) +- `dashboard.query` (aggregates + cache facade) + +--- + +## 4. Priority Mapping (Flaw -> SOLID-Driven Fix) + +1. Secret leaks and hardcoded config -> DIP (externalized secure config) + SRP (separate secret loading responsibility). +2. `permitAll` and CSRF disable -> DIP (policy abstraction) + SRP (security policy isolated). +3. UUID-only blacklist and IP handling gaps -> SRP (context extraction), OCP (extensible block keys). +4. MCP redundant analysis + blocked-user reprocessing -> SRP (pipeline steps), ISP (strategy classes by behavior), LSP (sync/async split). +5. Missing gRPC server + client mismatch -> DIP (ports/adapters), SRP (transport adapter separation). +6. Dashboard heavy DB load -> SRP (cache facade), OCP (cache strategy extension). +7. `parallelStream` misuse and `record.toString()` metadata storage -> SRP + DIP (serialization abstraction). + +--- + +## 5. Delivery Order for Implementation + +1. Phase 0 + Phase 1 (security-critical). +2. Phase 2 + Phase 3 (pipeline correctness and stability). +3. Phase 4 (data/query efficiency and observability quality). +4. Phase 5 + Phase 6 (resilience baseline and proof documentation). + +This order minimizes immediate breach risk first, then removes systemic runtime bottlenecks. From 0af6182e950ef6d5e4e28cc95934e5922333ad27 Mon Sep 17 00:00:00 2001 From: shrihari7396 Date: Sat, 4 Apr 2026 14:39:04 +0530 Subject: [PATCH 2/4] Repairing Started From Here ... --- .gitignore | 15 ++++ .idea/compiler.xml | 3 - .idea/modules.xml | 2 - .../pict/dtos/AnomalyDetectionRequest.java | 4 + .../pict/service/AnomalyDetectionService.java | 81 +++++++++++++++-- .../controller/ManagementController.java | 12 +-- .../filters/global/BlacklistFilter.java | 49 +++++++++-- .../filters/global/JwtExtractionFilter.java | 8 +- .../filters/global/SentientGateFilter.java | 87 ++++--------------- .../pict/apigateway/service/IpService.java | 38 +++++--- ApiGateway/src/main/resources/application.yml | 6 +- .../src/main/resources/application.yml.bak | 83 ------------------ LogingService/build.gradle | 34 ++++++++ .../entity/GatewayLogEntity.java | 9 +- .../repository/GatewayLogRepository.java | 1 + .../service/KafkaBatchService.java | 2 +- .../src/main/resources/application.yml | 16 ++-- MCPService/build.gradle | 1 + .../clients/AiServiceFeignClient.java | 4 +- .../kafkaListeners/SecurityEventListners.java | 35 +++++--- .../model/AnomalyDetectionResponse.java | 5 ++ .../edu/pict/mcpservice/service/AIClient.java | 4 +- .../service/EnforcementService.java | 70 +++++++++++++-- .../service/EventHistoryService.java | 18 +++- .../service/McpAnalysisService.java | 76 +++++++++++++--- .../blocking/AiAnomalyStrategy.java | 4 +- .../blocking/PatternMatchStrategy.java | 32 ++++++- MCPService/src/main/resources/application.yml | 11 ++- docker-compose.yml | 11 ++- private_key.pem | 28 ------ 30 files changed, 469 insertions(+), 280 deletions(-) delete mode 100644 ApiGateway/src/main/resources/application.yml.bak delete mode 100644 private_key.pem diff --git a/.gitignore b/.gitignore index 524f096..abc92aa 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,18 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* replay_pid* + +# Secrets and local config +*.pem +.env +.env.* +**/application.yml.bak + +# Build outputs +target/ +build/ +out/ + +# IDE/editor +.idea/ +.vscode/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml index eacdfcd..993ff64 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -21,9 +21,6 @@ - - -