Skip to content

Commit b6c6efb

Browse files
committed
Update counts when connected to chat with agents
1 parent 91beb16 commit b6c6efb

File tree

8 files changed

+113
-9
lines changed

8 files changed

+113
-9
lines changed

.local.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
SENTRIUS_VERSION=1.1.171
1+
SENTRIUS_VERSION=1.1.178
22
SENTRIUS_SSH_VERSION=1.1.33
33
SENTRIUS_KEYCLOAK_VERSION=1.1.46
44
SENTRIUS_AGENT_VERSION=1.1.33
55
SENTRIUS_AI_AGENT_VERSION=1.1.60
66
LLMPROXY_VERSION=1.0.43
77
LAUNCHER_VERSION=1.0.50
8-
AGENTPROXY_VERSION=1.0.60
8+
AGENTPROXY_VERSION=1.0.63

.local.env.bak

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
SENTRIUS_VERSION=1.1.171
1+
SENTRIUS_VERSION=1.1.178
22
SENTRIUS_SSH_VERSION=1.1.33
33
SENTRIUS_KEYCLOAK_VERSION=1.1.46
44
SENTRIUS_AGENT_VERSION=1.1.33
55
SENTRIUS_AI_AGENT_VERSION=1.1.60
66
LLMPROXY_VERSION=1.0.43
77
LAUNCHER_VERSION=1.0.50
8-
AGENTPROXY_VERSION=1.0.60
8+
AGENTPROXY_VERSION=1.0.63
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.sentrius.sso.controller;
2+
3+
import java.util.List;
4+
import io.sentrius.sso.core.dto.TerminalLogDTO;
5+
import io.sentrius.sso.service.ActiveWebSocketSessionManager;
6+
import org.springframework.http.HttpHeaders;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
import org.springframework.web.reactive.function.client.WebClient;
11+
import reactor.core.publisher.Mono;
12+
13+
@RestController
14+
@RequestMapping("/api/v1/sessions")
15+
public class SessionController {
16+
17+
private final WebClient webClient;
18+
private final ActiveWebSocketSessionManager activeWebSocketSessionManager;
19+
20+
public SessionController(WebClient.Builder builder, ActiveWebSocketSessionManager activeWebSocketSessionManager) {
21+
this.webClient = builder.baseUrl("http://sentrius-agent-proxy").build();
22+
this.activeWebSocketSessionManager = activeWebSocketSessionManager;
23+
}
24+
25+
@GetMapping("/list")
26+
public List<TerminalLogDTO> listSessions() {
27+
return activeWebSocketSessionManager.getActiveSessions();
28+
}
29+
30+
}

agent-proxy/src/main/java/io/sentrius/sso/service/ActiveWebSocketSessionManager.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package io.sentrius.sso.service;
22

3+
import java.sql.Timestamp;
4+
import java.util.List;
35
import java.util.Map;
6+
import java.util.Objects;
47
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.stream.Collectors;
9+
import io.sentrius.sso.core.dto.TerminalLogDTO;
510
import org.springframework.stereotype.Component;
611
import org.springframework.web.reactive.socket.WebSocketSession;
712

@@ -20,4 +25,16 @@ public void unregister(String sessionId) {
2025
public WebSocketSession get(String sessionId) {
2126
return sessions.get(sessionId);
2227
}
28+
29+
public List<TerminalLogDTO> getActiveSessions() {
30+
return sessions.values().stream()
31+
.map(session -> TerminalLogDTO.builder()
32+
.sessionId(session.getId())
33+
.user("Unknown")
34+
.host(Objects.requireNonNull(session.getHandshakeInfo().getRemoteAddress()).toString())
35+
.closed(!session.isOpen())
36+
.sessionTime(new Timestamp(System.currentTimeMillis()))
37+
.build())
38+
.collect(Collectors.toList());
39+
}
2340
}

api/src/main/java/io/sentrius/sso/controllers/api/AgentApiController.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ public ResponseEntity<?> heartbeat(
137137
log.warn("Heartbeat status is empty");
138138
return ResponseEntity.status(HttpStatus.SC_BAD_REQUEST).body("Heartbeat status is empty");
139139
}
140+
140141
agentService.recordHeartbeat(operatingUser.getUserId(),status.getName(), status);
142+
agentService.setCallBack(operatingUser, status.getAgentUrl());
141143
log.info("Heartbeat status recorded for agent: {} {}", agentId, status);
142144
return ResponseEntity.ok(Map.of("status", "success"));
143145
}

api/src/main/java/io/sentrius/sso/controllers/api/AuditApiController.java

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package io.sentrius.sso.controllers.api;
22

33
import java.security.GeneralSecurityException;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
46
import java.util.List;
57
import java.util.Map;
68
import java.util.stream.Collectors;
9+
import io.sentrius.sso.config.AppConfig;
710
import io.sentrius.sso.core.annotations.LimitAccess;
811
import io.sentrius.sso.core.config.SystemOptions;
912
import io.sentrius.sso.core.controllers.BaseController;
@@ -17,12 +20,18 @@
1720
import io.sentrius.sso.core.services.UserService;
1821
import io.sentrius.sso.core.services.auditing.AuditService;
1922
import io.sentrius.sso.core.services.security.CryptoService;
23+
import io.sentrius.sso.core.services.security.KeycloakService;
2024
import io.sentrius.sso.core.services.terminal.SessionTrackingService;
2125
import jakarta.servlet.http.HttpServletRequest;
2226
import jakarta.servlet.http.HttpServletResponse;
2327
import lombok.extern.slf4j.Slf4j;
28+
import org.springframework.http.HttpEntity;
29+
import org.springframework.http.HttpHeaders;
30+
import org.springframework.http.HttpMethod;
2431
import org.springframework.http.ResponseEntity;
2532
import org.springframework.web.bind.annotation.*;
33+
import org.springframework.web.client.RestTemplate;
34+
import org.springframework.web.reactive.function.client.WebClient;
2635

2736
@Slf4j
2837
@RestController
@@ -31,18 +40,32 @@ public class AuditApiController extends BaseController {
3140
private final AuditService auditService;
3241
final CryptoService cryptoService;
3342
final SessionTrackingService sessionTrackingService;
43+
final AppConfig appConfig;
44+
final RestTemplate restTemplate = new RestTemplate();
45+
final KeycloakService keycloakService;
46+
47+
private WebClient webClient;
3448

3549
public AuditApiController(
3650
UserService userService,
3751
SystemOptions systemOptions,
3852
ErrorOutputService errorOutputService,
3953
AuditService auditService,
40-
CryptoService cryptoService,SessionTrackingService sessionTrackingService
54+
CryptoService cryptoService, SessionTrackingService sessionTrackingService, AppConfig appConfig,
55+
KeycloakService keycloakService
4156
) {
4257
super(userService, systemOptions, errorOutputService);
4358
this.auditService = auditService;
4459
this.cryptoService = cryptoService;
4560
this.sessionTrackingService = sessionTrackingService;
61+
this.appConfig = appConfig;
62+
this.keycloakService = keycloakService;
63+
try {
64+
this.webClient = WebClient.builder().baseUrl(appConfig.getAgentProxyExternalUrl()).build();
65+
}
66+
catch (Exception e) {
67+
this.webClient = null;
68+
}
4669
}
4770

4871
public SessionLog createSession(@RequestParam String username, @RequestParam String ipAddress) {
@@ -57,14 +80,44 @@ public List<TerminalLogs> getLogs(@PathVariable Long sessionId) {
5780
@GetMapping("/list")
5881
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_LOG_IN}, sshAccess = {SSHAccessEnum.CAN_VIEW_SYSTEMS})
5982
public List<TerminalLogDTO> listOpenSessions(HttpServletRequest request, HttpServletResponse response) {
60-
return sessionTrackingService.getConnectedSession().stream().map(
83+
List<TerminalLogDTO> dtos = new ArrayList<>();
84+
sessionTrackingService.getConnectedSession().stream().map(
6185
x -> {
6286
try {
6387
return x.toDTO(cryptoService.encrypt(x.getSession().getId().toString()));
6488
} catch (GeneralSecurityException e) {
6589
throw new RuntimeException(e);
6690
}
67-
}).collect(Collectors.toList());
91+
}).forEach(dtos::add);
92+
93+
var agentProxyUrl = appConfig.getAgentProxyExternalUrl();
94+
95+
96+
try {
97+
98+
if (null != webClient) {
99+
HttpHeaders headers = new HttpHeaders();
100+
headers.setBearerAuth(keycloakService.getKeycloakToken()); // or however you're retrieving the token
101+
HttpEntity<?> requestEntity = new HttpEntity<>(headers);
102+
103+
var agentDtos = webClient.get()
104+
.uri("/api/v1/sessions/list")
105+
.header(HttpHeaders.AUTHORIZATION, "Bearer " + keycloakService.getKeycloakToken())
106+
.retrieve()
107+
.bodyToFlux(TerminalLogDTO.class)
108+
.collectList()
109+
.block(); // blocks for compatibility with a synchronous controller
110+
111+
if (agentDtos != null) dtos.addAll(agentDtos);
112+
} else {
113+
log.warn("Agent Proxy URL is not configured or WebClient could not be initialized. Cannot retrieve agent proxy sessions.");
114+
}
115+
} catch (Exception e) {
116+
log.warn("Failed to retrieve agent proxy sessions: {}", e.getMessage());
117+
}
118+
119+
120+
return dtos;
68121
}
69122

70123
@GetMapping("/audit/list")

api/src/main/resources/templates/fragments/dashboard/dashboard_cards.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<i class="fas fa-cog card-icon"></i> <!-- Icon for the card -->
55
</div>
66
<div class="card-body">
7-
<h5 class="card-title">Open SSH Connections</h5>
7+
<h5 class="card-title">Open Connections</h5>
88
<p class="card-text"><span id="open-cxn-count"></span></p>
99
</div>
1010
</div>

dataplane/src/main/java/io/sentrius/sso/core/services/agents/AgentService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ public List<AgentDTO> getAllAgents(boolean encryptId, List<String> filteredIds,
109109
.filter(heartbeat -> {
110110
var user = userService.getUserByUsername(heartbeat.getAgentName());
111111
log.info("Agent {}: {}", heartbeat.getAgentId(), user);
112-
log.info("Excluding {}: {}", heartbeat.getAgentId(), filteredIds);
112+
log.info("Excluding {}: {} -- include/exclude {}", heartbeat.getAgentId(), filteredIds, include);
113113
if (include){
114+
log.info("Including {}: {}", heartbeat.getAgentId(), filteredIds);
114115
return user != null && filteredIds.contains(user.getUserId());
115116
}
116117
else {
118+
log.info("Excluding {}: {}", heartbeat.getAgentId(), filteredIds);
117119
return user != null && !filteredIds.contains(user.getUserId());
118120
}
119121
})

0 commit comments

Comments
 (0)