Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .local.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SENTRIUS_VERSION=1.1.95
SENTRIUS_VERSION=1.1.97
SENTRIUS_SSH_VERSION=1.1.18
SENTRIUS_KEYCLOAK_VERSION=1.1.25
SENTRIUS_AGENT_VERSION=1.1.18
Expand Down
4 changes: 2 additions & 2 deletions .local.env.bak
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
SENTRIUS_VERSION=1.1.95
SENTRIUS_VERSION=1.1.96
SENTRIUS_SSH_VERSION=1.1.18
SENTRIUS_KEYCLOAK_VERSION=1.1.25
SENTRIUS_AGENT_VERSION=1.1.18
SENTRIUS_AI_AGENT_VERSION=1.1.33
LLMPROXY_VERSION=1.0.18
LAUNCHER_VERSION=1.0.28
LAUNCHER_VERSION=1.0.29
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

@RestController
@RequestMapping("/api/v1/policies")
Expand Down Expand Up @@ -59,4 +61,175 @@ public ResponseEntity<?> getPolicy(@PathVariable String policyId) {
}
return ResponseEntity.ok(policy);
}

@PostMapping("/validate")
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
public ResponseEntity<?> validatePolicy(@RequestBody ATPLPolicy policy) {
try {
Map<String, Object> validationResult = new HashMap<>();
validationResult.put("valid", true);
validationResult.put("errors", List.of());

// Basic validation
if (policy.getPolicyId() == null || policy.getPolicyId().trim().isEmpty()) {
validationResult.put("valid", false);
validationResult.put("errors", List.of("Policy ID is required"));
return ResponseEntity.ok(validationResult);
}

if (policy.getVersion() == null || policy.getVersion().trim().isEmpty()) {
validationResult.put("valid", false);
validationResult.put("errors", List.of("Version is required"));
return ResponseEntity.ok(validationResult);
}

if (policy.getCapabilities() == null) {
validationResult.put("valid", false);
validationResult.put("errors", List.of("Capabilities section is required"));
return ResponseEntity.ok(validationResult);
}

log.info("Policy validation passed for: {}", policy.getPolicyId());
return ResponseEntity.ok(validationResult);

} catch (Exception e) {
log.error("Error validating policy", e);
Map<String, Object> errorResult = new HashMap<>();
errorResult.put("valid", false);
errorResult.put("errors", List.of("Validation error: " + e.getMessage()));
return ResponseEntity.ok(errorResult);
}
}

@PostMapping("/measure")
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
public ResponseEntity<?> measureAgentCompliance(@RequestBody Map<String, Object> measurementRequest) {
try {
String policyId = (String) measurementRequest.get("policy_id");
Map<String, Object> agentActivity = (Map<String, Object>) measurementRequest.get("agent_activity");

if (policyId == null || agentActivity == null) {
return ResponseEntity.badRequest().body("policy_id and agent_activity are required");
}

ATPLPolicy policy = policyService.getPolicy(policyId);
if (policy == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Policy not found");
}

// Measurement engine logic
Map<String, Object> measurementResult = new HashMap<>();
measurementResult.put("policy_id", policyId);
measurementResult.put("compliance_score", calculateComplianceScore(policy, agentActivity));
measurementResult.put("within_bounds", true); // Simplified for now
measurementResult.put("violations", List.of());
measurementResult.put("timestamp", System.currentTimeMillis());

log.info("Measured agent compliance for policy: {}", policyId);
return ResponseEntity.ok(measurementResult);

} catch (Exception e) {
log.error("Error measuring agent compliance", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Measurement error: " + e.getMessage());
}
}

private double calculateComplianceScore(ATPLPolicy policy, Map<String, Object> agentActivity) {
// Simplified compliance scoring algorithm
double baseScore = 50.0;

// Check trust score requirements
if (policy.getTrustScore() != null && policy.getTrustScore().getMinimum() > 0) {
baseScore += 20.0;
}

// Check identity requirements
if (policy.getIdentity() != null) {
baseScore += 15.0;
}

// Check capabilities
if (policy.getCapabilities() != null) {
baseScore += 15.0;
}

return Math.min(100.0, baseScore);
}

@PostMapping("/test-endpoint")
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
public ResponseEntity<?> testEndpointAccess(@RequestBody Map<String, Object> testRequest) {
try {
String policyId = (String) testRequest.get("policy_id");
String method = (String) testRequest.get("method");
String path = (String) testRequest.get("path");

if (policyId == null || method == null || path == null) {
return ResponseEntity.badRequest().body("policy_id, method, and path are required");
}

ATPLPolicy policy = policyService.getPolicy(policyId);
if (policy == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Policy not found");
}

// Simulate endpoint access test
Map<String, Object> testResult = new HashMap<>();
testResult.put("policy_id", policyId);
testResult.put("method", method);
testResult.put("path", path);
testResult.put("allowed", true); // Simplified - would need actual endpoint matching logic
testResult.put("reason", "Endpoint access allowed by policy");
testResult.put("timestamp", System.currentTimeMillis());

log.info("Tested endpoint access for policy: {} - {} {}", policyId, method, path);
return ResponseEntity.ok(testResult);

} catch (Exception e) {
log.error("Error testing endpoint access", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Test error: " + e.getMessage());
}
}

@GetMapping("/templates")
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
public ResponseEntity<?> getPolicyTemplates() {
try {
Map<String, Object> templates = new HashMap<>();

// Web server template
Map<String, Object> webServer = new HashMap<>();
webServer.put("name", "Web Server Policy");
webServer.put("description", "Policy for web servers with basic HTTP access");
webServer.put("trust_score_minimum", 70);
webServer.put("endpoints", List.of(
Map.of("method", "GET", "path", "/", "action", "allow", "description", "Home page"),
Map.of("method", "GET", "path", "/static/*", "action", "allow", "description", "Static assets"),
Map.of("method", "GET", "path", "/health", "action", "allow", "description", "Health check")
));

// API service template
Map<String, Object> apiService = new HashMap<>();
apiService.put("name", "API Service Policy");
apiService.put("description", "Policy for REST API services");
apiService.put("trust_score_minimum", 80);
apiService.put("endpoints", List.of(
Map.of("method", "GET", "path", "/api/v1/*", "action", "allow", "description", "API endpoints"),
Map.of("method", "POST", "path", "/api/v1/*", "action", "allow", "description", "API creation"),
Map.of("method", "GET", "path", "/docs", "action", "allow", "description", "API documentation")
));

templates.put("web-server", webServer);
templates.put("api-service", apiService);

return ResponseEntity.ok(templates);

} catch (Exception e) {
log.error("Error getting policy templates", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Error getting templates: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.sentrius.sso.controllers.view;

import io.sentrius.sso.core.config.SystemOptions;
import io.sentrius.sso.core.controllers.BaseController;
import io.sentrius.sso.core.services.ATPLPolicyService;
import io.sentrius.sso.core.services.ErrorOutputService;
import io.sentrius.sso.core.services.UserService;
import io.sentrius.sso.core.trust.ATPLPolicy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Slf4j
@Controller
@RequestMapping("/sso/v1/atpl")
public class ATPLConfigController extends BaseController {

private final ATPLPolicyService atplPolicyService;

protected ATPLConfigController(
UserService userService,
SystemOptions systemOptions,
ErrorOutputService errorOutputService,
ATPLPolicyService atplPolicyService) {
super(userService, systemOptions, errorOutputService);
this.atplPolicyService = atplPolicyService;
}

@GetMapping("/configure")
public String configurePage(Model model) {
// Create empty policy template for new configurations
ATPLPolicy emptyPolicy = ATPLPolicy.builder()
.version("v0")
.build();

model.addAttribute("policy", emptyPolicy);
return "sso/atpl/configure";
}
}
13 changes: 9 additions & 4 deletions api/src/main/resources/templates/fragments/sidebar.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,15 @@
<i class="fa-solid fa-ticket"></i> <span class="ms-1 d-none d-sm-inline">System Integrations</span>
</a>
</li>
<li th:if="${#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_MANAGE_USERS')}">
<a href="/sso/v1/users/list" class="nav-link px-0 align-middle">
<i class="fa-solid fa-user"></i> <span class="ms-1 d-none d-sm-inline">Manage Agent/Users</span>
</a>
<li th:if="${#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_MANAGE_USERS')}">
<a href="/sso/v1/users/list" class="nav-link px-0 align-middle">
<i class="fa-solid fa-user"></i> <span class="ms-1 d-none d-sm-inline">Manage Agent/Users</span>
</a>
</li>
<li th:if="${#sets.contains(operatingUser.authorizationType.accessSet, 'CAN_MANAGE_APPLICATION')}">
<a href="/sso/v1/atpl/configure" class="nav-link px-0 align-middle">
<i class="fas fa-shield-alt"></i> <span class="ms-1 d-none d-sm-inline">ATPL Configuration</span>
</a>
</li>
</ul>
<hr>
Expand Down
Loading
Loading