From 495dea2382d13cd3d81293a4300525f7fc45a183 Mon Sep 17 00:00:00 2001 From: Marc Parisi Date: Mon, 7 Jul 2025 07:06:28 -0400 Subject: [PATCH 1/5] Refresh instead of reload page --- .../api/ZeroTrustATApiController.java | 75 +++++ .../templates/sso/ztats/view_ztats.html | 263 +++++++++++++++++- .../security/ZeroTrustAccessTokenService.java | 21 +- ops-scripts/local/deploy-helm.sh | 4 +- 4 files changed, 344 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java b/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java index a82edc5e..d35eaaea 100644 --- a/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java +++ b/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java @@ -327,6 +327,81 @@ public ResponseEntity listZtatRequests(@RequestHeader("Authorization") String return ResponseEntity.ok(ztatTracker); } + @GetMapping("/list/{state}/{type}") + @LimitAccess(ztatAccess = {ZeroTrustAccessTokenEnum.CAN_VIEW_ZTATS}) + public ResponseEntity listTypedZtatRequests(@RequestHeader("Authorization") String token, + @PathVariable("type") String type, + @PathVariable("state") String state, + HttpServletRequest request, HttpServletResponse response) { + String compactJwt = token.startsWith("Bearer ") ? token.substring(7) : token; + + + log.info("Received ZTAT request from agent: {}", compactJwt); + if (!keycloakService.validateJwt(compactJwt)) { + log.warn("Invalid Keycloak token"); + return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).body("Invalid Keycloak token"); + } + + // Extract agent identity from the JWT + var operatingUser = getOperatingUser(request, response ); + + // Extract agent identity from the JWT + String agentId = keycloakService.extractAgentId(compactJwt); + + if (null == operatingUser) { + log.warn("No operating user found for agent: {}", agentId); + var username = keycloakService.extractUsername(compactJwt); + operatingUser = userService.getUserByUsername(username); + + } + List ztatTracker = new ArrayList(); + switch(type){ + case "terminal": + if ("denied".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getDeniedJITRequests(operatingUser); + } else if ("approved".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getApprovedJITRequests(operatingUser); + } else { + ztatTracker = ztatService.getOpenJITRequests(operatingUser); + } + break; + case "ops": + if ("denied".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getDeniedOpsJITRequests(operatingUser); + } else if ("approved".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getApprovedOpsJITRequests(operatingUser); + } else { + ztatTracker = ztatService.getOpenOpsRequests(operatingUser); + } + break; + case "atat": + if ("denied".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getDeniedOpsJITRequests(operatingUser); + } else if ("approved".equalsIgnoreCase(state)) { + ztatTracker = ztatService.getApprovedOpsJITRequests(operatingUser); + } else { + ztatTracker = ztatService.getOpenOpsRequests(operatingUser); + } + ztatTracker = ztatTracker.stream().filter(dto -> { + if (dto.getCommand().equals("register")) { + return false; + } + try { + if (userService.isNPE(dto.getUserName())){ + return true; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return false; + }).toList(); + break; + default: + log.warn("Invalid type: {}", type); + } + return ResponseEntity.ok(ztatTracker); + } + @PostMapping("/jwt/issue") public ResponseEntity issueZtat(@RequestBody UserTokenDTO request) { String ztat = tokenService.issueZtat(request.getUserId(), request.getSessionId(), request.getPublicKey()); diff --git a/api/src/main/resources/templates/sso/ztats/view_ztats.html b/api/src/main/resources/templates/sso/ztats/view_ztats.html index 2d326382..9d21291d 100755 --- a/api/src/main/resources/templates/sso/ztats/view_ztats.html +++ b/api/src/main/resources/templates/sso/ztats/view_ztats.html @@ -254,39 +254,272 @@

Trust AT (TAT) Management

diff --git a/dataplane/src/main/java/io/sentrius/sso/core/services/security/ZeroTrustAccessTokenService.java b/dataplane/src/main/java/io/sentrius/sso/core/services/security/ZeroTrustAccessTokenService.java index 907f5762..aeb7d19f 100644 --- a/dataplane/src/main/java/io/sentrius/sso/core/services/security/ZeroTrustAccessTokenService.java +++ b/dataplane/src/main/java/io/sentrius/sso/core/services/security/ZeroTrustAccessTokenService.java @@ -277,10 +277,25 @@ public boolean hasJITRequest(String command, User user, HostSystem system) { return ztatRequestService.hasJITRequest(command, user.getId(), system.getId()); } - public List getOpenJITRequests(User operatingUser) { - return ztatRequestService.getOpenAccessTokenRequests(operatingUser); - } + public List getOpenJITRequests(User operatingUser) { + return ztatRequestService.getOpenAccessTokenRequests(operatingUser); + } + public List getDeniedJITRequests(User operatingUser) { + return ztatRequestService.getDeniedTerminalAccessTokenRequests(operatingUser); + } + + public List getDeniedOpsJITRequests(User operatingUser) { + return ztatRequestService.getDeniedOpsAccessTokenRequests(operatingUser); + } + + public List getApprovedJITRequests(User operatingUser) { + return ztatRequestService.getApprovedTerminalAccessTokenRequests(operatingUser); + } + + public List getApprovedOpsJITRequests(User operatingUser) { + return ztatRequestService.getApprovedOpsAccessTokenRequests(operatingUser); + } public List getOpenOpsRequests(User operatingUser) { return ztatRequestService.getOpenOpsRequests(operatingUser); } diff --git a/ops-scripts/local/deploy-helm.sh b/ops-scripts/local/deploy-helm.sh index ecada310..3a3bb5c7 100755 --- a/ops-scripts/local/deploy-helm.sh +++ b/ops-scripts/local/deploy-helm.sh @@ -14,6 +14,8 @@ ENABLE_TLS=false INSTALL_CERT_MANAGER=false ENV_TARGET="local" # default mode CERT_DIR="${SCRIPT_DIR}/../../docker/dev-certs" +# set default to false +DEPLOY_ADMINER=${DEPLOY_ADMINER:-false} # --- Load and back up environment file --- ENV_FILE="${SCRIPT_DIR}/../../.$ENV_TARGET.env" @@ -208,7 +210,7 @@ if [[ -z "$KEYCLOAK_CLIENT_SECRET" ]]; then fi helm upgrade --install sentrius ./sentrius-chart --namespace ${TENANT} \ - --set adminer.enabled=true \ + --set adminer.enabled=${DEPLOY_ADMINER} \ --set tenant=${TENANT} \ --set environment=${ENVIRONMENT} \ --set subdomain="${SUBDOMAIN}" \ From 8244f065a9a59122999866009e8409084ac269ae Mon Sep 17 00:00:00 2001 From: Marc Date: Mon, 7 Jul 2025 07:10:15 -0400 Subject: [PATCH 2/5] Update api/src/main/resources/templates/sso/ztats/view_ztats.html Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marc --- api/src/main/resources/templates/sso/ztats/view_ztats.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/main/resources/templates/sso/ztats/view_ztats.html b/api/src/main/resources/templates/sso/ztats/view_ztats.html index 9d21291d..83f11936 100755 --- a/api/src/main/resources/templates/sso/ztats/view_ztats.html +++ b/api/src/main/resources/templates/sso/ztats/view_ztats.html @@ -385,7 +385,8 @@

Trust AT (TAT) Management

$table.row.add([ s.summary, s.userName, - s.usesRemaining + s.usesRemaining, + actions ]); } From da1446dc52747a954395560f40c67f47d1244c97 Mon Sep 17 00:00:00 2001 From: Marc Date: Mon, 7 Jul 2025 07:10:33 -0400 Subject: [PATCH 3/5] Update api/src/main/resources/templates/sso/ztats/view_ztats.html Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Marc --- api/src/main/resources/templates/sso/ztats/view_ztats.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/resources/templates/sso/ztats/view_ztats.html b/api/src/main/resources/templates/sso/ztats/view_ztats.html index 83f11936..6756f2fe 100755 --- a/api/src/main/resources/templates/sso/ztats/view_ztats.html +++ b/api/src/main/resources/templates/sso/ztats/view_ztats.html @@ -521,6 +521,8 @@

Trust AT (TAT) Management

}); attachZtatButtonHandlers(); + reloadTerminalTATs(); + reloadOpsTATs(); }); From 43e457b2b5d9c7ee85a14ebc427e46149da2891a Mon Sep 17 00:00:00 2001 From: Marc Parisi Date: Mon, 7 Jul 2025 08:35:14 -0400 Subject: [PATCH 4/5] Fix issue with ztats not reloading --- .../api/ZeroTrustATApiController.java | 91 ++++++++++++------- .../templates/sso/ztats/view_ztats.html | 81 ++++++++++------- .../security/ZeroTrustRequestService.java | 4 + 3 files changed, 112 insertions(+), 64 deletions(-) diff --git a/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java b/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java index d35eaaea..09a482a2 100644 --- a/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java +++ b/api/src/main/java/io/sentrius/sso/controllers/api/ZeroTrustATApiController.java @@ -33,6 +33,7 @@ import io.sentrius.sso.core.services.security.KeycloakService; import io.sentrius.sso.core.services.security.ZeroTrustAccessTokenService; import io.sentrius.sso.core.services.security.ZtatTokenService; +import io.sentrius.sso.core.utils.AccessUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -273,28 +274,27 @@ public ResponseEntity getRequest(HttpServletRequest request, HttpServletRespo @GetMapping("/list/{type}") @LimitAccess(ztatAccess = {ZeroTrustAccessTokenEnum.CAN_VIEW_ZTATS}) - public ResponseEntity listZtatRequests(@RequestHeader("Authorization") String token, + public ResponseEntity listZtatRequests(@RequestHeader(name= "Authorization", required=false) String token, @PathVariable("type") String type, HttpServletRequest request, HttpServletResponse response) { - String compactJwt = token.startsWith("Bearer ") ? token.substring(7) : token; + var operatingUser = getOperatingUser(request, response ); + if (null != token) { + String compactJwt = token.startsWith("Bearer ") ? token.substring(7) : token; - log.info("Received ZTAT request from agent: {}", compactJwt); - if (!keycloakService.validateJwt(compactJwt)) { - log.warn("Invalid Keycloak token"); - return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).body("Invalid Keycloak token"); - } + log.info("Received ZTAT request from agent: {}", compactJwt); + if (!keycloakService.validateJwt(compactJwt)) { + log.warn("Invalid Keycloak token"); + return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).body("Invalid Keycloak token"); + } + String agentId = keycloakService.extractAgentId(compactJwt); - // Extract agent identity from the JWT - var operatingUser = getOperatingUser(request, response ); + if (null == operatingUser) { + log.warn("No operating user found for agent: {}", agentId); + var username = keycloakService.extractUsername(compactJwt); + operatingUser = userService.getUserByUsername(username); - // Extract agent identity from the JWT - String agentId = keycloakService.extractAgentId(compactJwt); - - if (null == operatingUser) { - log.warn("No operating user found for agent: {}", agentId); - var username = keycloakService.extractUsername(compactJwt); - operatingUser = userService.getUserByUsername(username); + } } List ztatTracker = new ArrayList(); @@ -324,36 +324,42 @@ public ResponseEntity listZtatRequests(@RequestHeader("Authorization") String default: log.warn("Invalid type: {}", type); } + ztatTracker = decorateTats(ztatTracker, operatingUser); return ResponseEntity.ok(ztatTracker); } @GetMapping("/list/{state}/{type}") @LimitAccess(ztatAccess = {ZeroTrustAccessTokenEnum.CAN_VIEW_ZTATS}) - public ResponseEntity listTypedZtatRequests(@RequestHeader("Authorization") String token, + public ResponseEntity listTypedZtatRequests(@RequestHeader(name= "Authorization", required=false) String token, @PathVariable("type") String type, @PathVariable("state") String state, HttpServletRequest request, HttpServletResponse response) { - String compactJwt = token.startsWith("Bearer ") ? token.substring(7) : token; + var operatingUser = getOperatingUser(request, response ); + if (null != token) { + String compactJwt = token.startsWith("Bearer ") ? token.substring(7) : token; - log.info("Received ZTAT request from agent: {}", compactJwt); - if (!keycloakService.validateJwt(compactJwt)) { - log.warn("Invalid Keycloak token"); - return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).body("Invalid Keycloak token"); - } - // Extract agent identity from the JWT - var operatingUser = getOperatingUser(request, response ); + log.info("Received ZTAT request from agent: {}", compactJwt); + if (!keycloakService.validateJwt(compactJwt)) { + log.warn("Invalid Keycloak token"); + return ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).body("Invalid Keycloak token"); + } + String agentId = keycloakService.extractAgentId(compactJwt); - // Extract agent identity from the JWT - String agentId = keycloakService.extractAgentId(compactJwt); + if (null == operatingUser) { + log.warn("No operating user found for agent: {}", agentId); + var username = keycloakService.extractUsername(compactJwt); + operatingUser = userService.getUserByUsername(username); - if (null == operatingUser) { - log.warn("No operating user found for agent: {}", agentId); - var username = keycloakService.extractUsername(compactJwt); - operatingUser = userService.getUserByUsername(username); + } } + // Extract agent identity from the JWT + + + // Extract agent identity from the JWT + List ztatTracker = new ArrayList(); switch(type){ case "terminal": @@ -399,6 +405,7 @@ public ResponseEntity listTypedZtatRequests(@RequestHeader("Authorization") S default: log.warn("Invalid type: {}", type); } + ztatTracker = decorateTats(ztatTracker, operatingUser); return ResponseEntity.ok(ztatTracker); } @@ -439,4 +446,26 @@ public ResponseEntity verifyZtat(@RequestBody ZtatChallengeRequest requ } } + List decorateTats(List tats, User operatingUser){ + boolean canApprove = AccessUtil.canAccess(operatingUser, ZeroTrustAccessTokenEnum.CAN_APPROVE_ZTATS); + boolean canDeny = AccessUtil.canAccess(operatingUser, ZeroTrustAccessTokenEnum.CAN_DENY_ZTATS); + if (canApprove || canDeny) { + for (var tat : tats) { + + if (tat.getUserName().equals(operatingUser.getUsername())) { + tat.setCurrentUser(true); + if (systemOptions.getCanApproveOwnZtat()) { + tat.setCanApprove(canApprove); + tat.setCanDeny(canDeny); + } + } + else { + tat.setCanApprove(canApprove); + tat.setCanDeny(canDeny); + } + + } + } + return tats; + } } diff --git a/api/src/main/resources/templates/sso/ztats/view_ztats.html b/api/src/main/resources/templates/sso/ztats/view_ztats.html index 6756f2fe..ed02eb0b 100755 --- a/api/src/main/resources/templates/sso/ztats/view_ztats.html +++ b/api/src/main/resources/templates/sso/ztats/view_ztats.html @@ -86,6 +86,7 @@

Trust AT (TAT) Management

OperationUserSystemActions + @@ -110,6 +112,7 @@

Trust AT (TAT) Management

OperationUserActions + @@ -150,6 +154,7 @@

Trust AT (TAT) Management

RemainingActions + @@ -172,6 +178,7 @@

Trust AT (TAT) Management

+ @@ -189,8 +197,8 @@

Trust AT (TAT) Management

- - + +
@@ -207,6 +215,7 @@

Trust AT (TAT) Management

OperationUserSystemActions +
@@ -227,6 +237,7 @@

Trust AT (TAT) Management

OperationUserActions + @@ -247,10 +259,10 @@

Trust AT (TAT) Management

+ + - -