Skip to content

Commit 3395238

Browse files
Copilotphrocker
andcommitted
Implement endpoint scanning and capabilities API
Co-authored-by: phrocker <[email protected]>
1 parent 3c239e1 commit 3395238

File tree

6 files changed

+554
-0
lines changed

6 files changed

+554
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package io.sentrius.sso.controllers.api;
2+
3+
import io.sentrius.sso.core.annotations.LimitAccess;
4+
import io.sentrius.sso.core.config.SystemOptions;
5+
import io.sentrius.sso.core.controllers.BaseController;
6+
import io.sentrius.sso.core.dto.capabilities.EndpointDescriptor;
7+
import io.sentrius.sso.core.model.security.enums.ApplicationAccessEnum;
8+
import io.sentrius.sso.core.services.ErrorOutputService;
9+
import io.sentrius.sso.core.services.UserService;
10+
import io.sentrius.sso.core.services.capabilities.EndpointScanningService;
11+
import jakarta.servlet.http.HttpServletRequest;
12+
import jakarta.servlet.http.HttpServletResponse;
13+
import lombok.extern.slf4j.Slf4j;
14+
import org.springframework.http.ResponseEntity;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
import org.springframework.web.bind.annotation.RequestMapping;
17+
import org.springframework.web.bind.annotation.RequestParam;
18+
import org.springframework.web.bind.annotation.RestController;
19+
20+
import java.util.List;
21+
import java.util.stream.Collectors;
22+
23+
/**
24+
* API controller for exposing endpoint capabilities across the system.
25+
* This provides a unified view of all REST endpoints and Verb methods available.
26+
*/
27+
@Slf4j
28+
@RestController
29+
@RequestMapping("/api/v1/capabilities")
30+
public class CapabilitiesApiController extends BaseController {
31+
32+
private final EndpointScanningService endpointScanningService;
33+
34+
public CapabilitiesApiController(
35+
UserService userService,
36+
SystemOptions systemOptions,
37+
ErrorOutputService errorOutputService,
38+
EndpointScanningService endpointScanningService) {
39+
super(userService, systemOptions, errorOutputService);
40+
this.endpointScanningService = endpointScanningService;
41+
}
42+
43+
/**
44+
* Returns all available endpoints (REST and Verb) in the system.
45+
* This can be used by AI agents and other systems to understand what capabilities are available.
46+
*/
47+
@GetMapping("/endpoints")
48+
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_LOG_IN})
49+
public ResponseEntity<List<EndpointDescriptor>> getAllEndpoints(
50+
@RequestParam(required = false) String type,
51+
@RequestParam(required = false) Boolean requiresAuth,
52+
HttpServletRequest request,
53+
HttpServletResponse response) {
54+
55+
log.info("Retrieving all endpoints with filters - type: {}, requiresAuth: {}", type, requiresAuth);
56+
57+
List<EndpointDescriptor> endpoints = endpointScanningService.getAllEndpoints();
58+
59+
// Apply filters if provided
60+
if (type != null) {
61+
endpoints = endpoints.stream()
62+
.filter(endpoint -> type.equalsIgnoreCase(endpoint.getType()))
63+
.collect(Collectors.toList());
64+
}
65+
66+
if (requiresAuth != null) {
67+
endpoints = endpoints.stream()
68+
.filter(endpoint -> endpoint.isRequiresAuthentication() == requiresAuth)
69+
.collect(Collectors.toList());
70+
}
71+
72+
log.info("Returning {} endpoints", endpoints.size());
73+
return ResponseEntity.ok(endpoints);
74+
}
75+
76+
/**
77+
* Returns only REST API endpoints.
78+
*/
79+
@GetMapping("/rest")
80+
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_LOG_IN})
81+
public ResponseEntity<List<EndpointDescriptor>> getRestEndpoints(
82+
HttpServletRequest request,
83+
HttpServletResponse response) {
84+
85+
log.info("Retrieving REST endpoints");
86+
87+
List<EndpointDescriptor> endpoints = endpointScanningService.getAllEndpoints()
88+
.stream()
89+
.filter(endpoint -> "REST".equals(endpoint.getType()))
90+
.collect(Collectors.toList());
91+
92+
log.info("Returning {} REST endpoints", endpoints.size());
93+
return ResponseEntity.ok(endpoints);
94+
}
95+
96+
/**
97+
* Returns only Verb methods (for AI agents).
98+
*/
99+
@GetMapping("/verbs")
100+
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_LOG_IN})
101+
public ResponseEntity<List<EndpointDescriptor>> getVerbEndpoints(
102+
HttpServletRequest request,
103+
HttpServletResponse response) {
104+
105+
log.info("Retrieving Verb endpoints");
106+
107+
List<EndpointDescriptor> endpoints = endpointScanningService.getAllEndpoints()
108+
.stream()
109+
.filter(endpoint -> "VERB".equals(endpoint.getType()))
110+
.collect(Collectors.toList());
111+
112+
log.info("Returning {} Verb endpoints", endpoints.size());
113+
return ResponseEntity.ok(endpoints);
114+
}
115+
116+
/**
117+
* Forces a refresh of the endpoint cache.
118+
* This can be useful during development or after deploying new capabilities.
119+
*/
120+
@GetMapping("/refresh")
121+
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
122+
public ResponseEntity<String> refreshEndpoints(
123+
HttpServletRequest request,
124+
HttpServletResponse response) {
125+
126+
log.info("Refreshing endpoint cache");
127+
endpointScanningService.refreshEndpoints();
128+
129+
int count = endpointScanningService.getAllEndpoints().size();
130+
String message = String.format("Endpoint cache refreshed. Found %d endpoints.", count);
131+
132+
log.info(message);
133+
return ResponseEntity.ok(message);
134+
}
135+
}

core/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@
193193
<groupId>io.opentelemetry</groupId>
194194
<artifactId>opentelemetry-exporter-otlp</artifactId>
195195
</dependency>
196+
197+
<!-- ClassGraph for classpath scanning -->
198+
<dependency>
199+
<groupId>io.github.classgraph</groupId>
200+
<artifactId>classgraph</artifactId>
201+
</dependency>
196202

197203
</dependencies>
198204

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.sentrius.sso.core.dto.capabilities;
2+
3+
import io.sentrius.sso.core.data.EndpointThreat;
4+
import io.sentrius.sso.core.model.security.enums.ApplicationAccessEnum;
5+
import io.sentrius.sso.core.model.security.enums.IdentityType;
6+
import io.sentrius.sso.core.model.security.enums.RuleAccessEnum;
7+
import io.sentrius.sso.core.model.security.enums.SSHAccessEnum;
8+
import io.sentrius.sso.core.model.security.enums.SystemOperationsEnum;
9+
import io.sentrius.sso.core.model.security.enums.UserAccessEnum;
10+
import io.sentrius.sso.core.model.security.enums.ZeroTrustAccessTokenEnum;
11+
import lombok.Builder;
12+
import lombok.Data;
13+
import lombok.Getter;
14+
import lombok.Setter;
15+
16+
/**
17+
* Represents access limitations extracted from @LimitAccess annotation.
18+
*/
19+
@Builder
20+
@Data
21+
@Getter
22+
@Setter
23+
public class AccessLimitations {
24+
private String notificationMessage;
25+
private IdentityType[] allowedIdentityTypes;
26+
private UserAccessEnum[] userAccess;
27+
private ApplicationAccessEnum[] applicationAccess;
28+
private RuleAccessEnum[] ruleAccess;
29+
private SSHAccessEnum[] sshAccess;
30+
private SystemOperationsEnum[] systemOperations;
31+
private ZeroTrustAccessTokenEnum[] ztatAccess;
32+
private EndpointThreat endpointThreat;
33+
34+
@Builder.Default
35+
private boolean hasLimitAccess = false;
36+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package io.sentrius.sso.core.dto.capabilities;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.Getter;
8+
import lombok.Setter;
9+
10+
/**
11+
* Represents a unified descriptor for both REST API endpoints and Verb methods.
12+
* This allows for a consistent way to describe all capabilities across the system.
13+
*/
14+
@Builder
15+
@Data
16+
@Getter
17+
@Setter
18+
public class EndpointDescriptor {
19+
private String name;
20+
private String description;
21+
private String type; // "REST" or "VERB"
22+
private String httpMethod; // GET, POST, etc. (null for verbs)
23+
private String path; // REST path (null for verbs)
24+
private String className; // Class containing the method
25+
private String methodName; // Method name
26+
private List<ParameterDescriptor> parameters;
27+
private AccessLimitations accessLimitations;
28+
private Map<String, Object> metadata; // Additional metadata
29+
30+
@Builder.Default
31+
private boolean requiresAuthentication = true;
32+
33+
@Builder.Default
34+
private boolean requiresTokenManagement = false;
35+
36+
private Class<?> returnType;
37+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.sentrius.sso.core.dto.capabilities;
2+
3+
import lombok.Builder;
4+
import lombok.Data;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
8+
/**
9+
* Describes a parameter for an endpoint (either REST or Verb).
10+
*/
11+
@Builder
12+
@Data
13+
@Getter
14+
@Setter
15+
public class ParameterDescriptor {
16+
private String name;
17+
private String description;
18+
private Class<?> type;
19+
private boolean required;
20+
private Object defaultValue;
21+
private String source; // "PATH", "QUERY", "BODY", "HEADER", "METHOD_PARAM"
22+
}

0 commit comments

Comments
 (0)