Skip to content

Commit f8e19ff

Browse files
committed
Incremental commit
1 parent 6fa1712 commit f8e19ff

File tree

12 files changed

+152
-23
lines changed

12 files changed

+152
-23
lines changed

ai-agent/src/main/java/io/sentrius/agent/analysis/agents/agents/ChatAgent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public void onApplicationEvent(final ApplicationReadyEvent event) {
8686
var encryptedSecret = agentRegistrationDTO.getClientSecret();
8787
var decryptedSecret = agentKeyService.
8888
decryptWithPrivateKey(encryptedSecret, keyPair.getPrivate());
89-
keycloakService.createKeycloakClient(agentRegistrationDTO.getAgentName(),
89+
keycloakService.createKeycloakClient(agentConfigOptions.getName(),
9090
decryptedSecret);
9191

9292

@@ -131,7 +131,7 @@ public void onApplicationEvent(final ApplicationReadyEvent event) {
131131

132132
while(running) {
133133

134-
log.info("Registering v1.0.2 agent failed. Retrying in 10 seconds...");
134+
log.info("Agent Registered...");
135135
try {
136136

137137
Thread.sleep(5_000);

ai-agent/src/main/java/io/sentrius/agent/analysis/api/AgentController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public ResponseEntity<AgentRegistrationDTO> describeAgent() {
5858
.agentName(agentConfig.getName())
5959
.agentPublicKey(agentKeyService.getKeyPair().getPublic().toString())
6060
.agentPublicKeyAlgo(agentKeyService.getKeyPair().getPublic().getAlgorithm())
61+
.agentType(agentConfig.getType())
6162
.build();
6263
return ResponseEntity.ok(dto);
6364
}

ai-agent/src/main/java/io/sentrius/agent/config/AgentConfigOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ public class AgentConfigOptions {
1515

1616

1717
private String name;
18+
private String type;
1819
}

ai-agent/src/main/resources/chat-helper.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,5 @@ otel.metrics.exporter=none
7878
otel.logs.exporter=none
7979
otel.resource.attributes.service.name=chat-helper
8080
otel.traces.sampler=always_on
81-
otel.exporter.otlp.timeout=10s
81+
otel.exporter.otlp.timeout=10s
82+
agent.type="chat-helper"

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

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package io.sentrius.sso.controllers.api;
22

3+
import java.io.IOException;
4+
import java.io.InputStream;
35
import java.security.GeneralSecurityException;
46
import java.sql.SQLException;
57
import io.sentrius.sso.config.ApiPaths;
68
import io.sentrius.sso.core.config.SystemOptions;
79
import io.sentrius.sso.core.controllers.BaseController;
810
import io.sentrius.sso.core.dto.AgentRegistrationDTO;
11+
import io.sentrius.sso.core.model.security.IdentityType;
12+
import io.sentrius.sso.core.model.security.UserType;
13+
import io.sentrius.sso.core.model.users.User;
914
import io.sentrius.sso.core.services.ATPLPolicyService;
1015
import io.sentrius.sso.core.services.ErrorOutputService;
1116
import io.sentrius.sso.core.services.UserService;
@@ -19,6 +24,7 @@
1924
import jakarta.servlet.http.HttpServletRequest;
2025
import jakarta.servlet.http.HttpServletResponse;
2126
import lombok.extern.slf4j.Slf4j;
27+
import org.springframework.beans.factory.annotation.Value;
2228
import org.springframework.http.ResponseEntity;
2329
import org.springframework.web.bind.annotation.GetMapping;
2430
import org.springframework.web.bind.annotation.PostMapping;
@@ -39,6 +45,13 @@ public class AgentBootstrapController extends BaseController {
3945
final ZeroTrustRequestService ztrService;
4046
final AgentService agentService;
4147

48+
49+
@Value("${sentrius.agent.register.bootstrap.allow:false}")
50+
private boolean allowRegistration;
51+
52+
@Value("${sentrius.agent.bootstrap.policy:default-policy.yaml}")
53+
private String defaultPolicyFile;
54+
4255
public AgentBootstrapController(
4356
UserService userService,
4457
SystemOptions systemOptions,
@@ -62,22 +75,56 @@ public AgentBootstrapController(
6275

6376
@PostMapping("/register")
6477
// no LimitAccess
65-
public ResponseEntity<AgentRegistrationDTO> bootsrap(
66-
@RequestBody AgentRegistrationDTO registrationDTO) throws GeneralSecurityException {
78+
public ResponseEntity<AgentRegistrationDTO> bootstrap(
79+
@RequestBody AgentRegistrationDTO registrationDTO) throws GeneralSecurityException, IOException {
6780
log.info("Registering agent {}", registrationDTO);
68-
var secret = keycloakService.registerAgentClient(registrationDTO.getAgentName());
81+
// need a pre-shared secret to register the agent or ztat approval
82+
var unencryptedRegistration = keycloakService.registerAgentClient(registrationDTO);
6983

70-
var secretKey = CryptoService.encryptWithPublicKey(secret,
84+
var secretKey = CryptoService.encryptWithPublicKey(unencryptedRegistration.getClientSecret(),
7185
CryptoService.decodePublicKey(registrationDTO.getAgentPublicKey(),
7286
registrationDTO.getAgentPublicKeyAlgo()));
7387

7488
var newDTO = AgentRegistrationDTO.builder()
75-
.agentName(registrationDTO.getAgentName())
89+
.agentName(unencryptedRegistration.getAgentName())
7690
.agentPublicKey(registrationDTO.getAgentPublicKey())
7791
.agentPublicKeyAlgo(registrationDTO.getAgentPublicKeyAlgo())
7892
.clientSecret(secretKey)
93+
.clientId(unencryptedRegistration.getClientId())
7994
.build();
8095

96+
if (allowRegistration) {
97+
log.info("Registering {}", registrationDTO.getAgentName());
98+
User user = userService.getUserByUsername(newDTO.getAgentName());
99+
if (user == null) {
100+
var type = userService.getUserType(
101+
UserType.createUnknownUser());
102+
103+
user = User.builder()
104+
.username(newDTO.getAgentName())
105+
.name(newDTO.getAgentName())
106+
.emailAddress(newDTO.getAgentName())
107+
.userId(unencryptedRegistration.getClientId())
108+
.authorizationType(type.get())
109+
.identityType(IdentityType.NON_PERSON_ENTITY)
110+
.build();
111+
log.info("Creating new user: {}", user);
112+
userService.save(user);
113+
}
114+
try(InputStream terminalHelperStream = getClass().getClassLoader().getResourceAsStream(defaultPolicyFile)) {
115+
if (terminalHelperStream == null) {
116+
throw new RuntimeException(defaultPolicyFile + "not found on classpath");
117+
118+
}
119+
String defaultYaml = new String(terminalHelperStream.readAllBytes());
120+
log.info("Default policy file: {}", defaultPolicyFile);
121+
var policy = atplPolicyService.createPolicy(user, defaultYaml);
122+
}
123+
124+
}
125+
else {
126+
log.info("Not Registering {}", registrationDTO.getAgentName());
127+
}
81128
// bootstrap with a default policy
82129
return ResponseEntity.ok(newDTO);
83130
}

api/src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,6 @@ otel.logs.exporter=none
8888
otel.resource.attributes.service.name=sentrius-api
8989
otel.traces.sampler=always_on
9090
otel.exporter.otlp.timeout=10s
91+
92+
sentrius.agent.register.bootstrap.allow=true
93+
sentrius.agent.bootstrap.policy=default-policy.yaml
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
version: "v0"
3+
description: "Default Policy For Unregistered Agents ( if configured )"
4+
match:
5+
agent_tags:
6+
- "env:prod"
7+
- "classification:observer"
8+
behavior:
9+
minimum_positive_runs: 5
10+
max_incidents: 1
11+
incident_types:
12+
denylist:
13+
- "policy_violation"
14+
actions:
15+
on_success: "allow"
16+
on_failure: "deny"
17+
on_marginal:
18+
action: "require_ztat"
19+
ztat_provider: "ztat-service.internal"
20+
capabilities:
21+
primitives:
22+
composed:
23+
ztat:
24+
provider: "ztat-service.internal"
25+
ttl: "5m"
26+
approved_issuers:
27+
- "http://localhost:8080/"
28+
key_binding: "RSA2048"
29+
approval_required: true
30+
policy_id: "f3326ce2-f46f-405d-94b6-bda2b26db423"
31+
identity:
32+
issuer: "https://keycloak.test.sentrius.cloud"
33+
subject_prefix: "agent-"
34+
mfa_required: true
35+
certificate_authority: "Sentrius-CA"
36+
provenance:
37+
source: "https://test.sentrius.cloud"
38+
signature_required: true
39+
approved_committers:
40+
41+
runtime:
42+
enclave_required: true
43+
attestation_type: "aws-nitro"
44+
verified_at_boot: true
45+
allow_drift: true
46+
trust_score:
47+
minimum: 80
48+
marginalThreshold: 50
49+
weightings:
50+
identity: 0.5
51+
provenance: 0.2
52+
runtime: 0.3
53+
behavior: 0.2

api/src/test/resources/default-policy.yaml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
version: "v0"
3-
description: "Default Policy For Chat Agents"
3+
description: "Default Policy For Unregistered Agents ( if configured )"
44
match:
55
agent_tags:
66
- "env:prod"
@@ -19,18 +19,7 @@ actions:
1919
ztat_provider: "ztat-service.internal"
2020
capabilities:
2121
primitives:
22-
- id: "accessLLM"
23-
description: "access llm"
24-
endpoint:
25-
- "/api/v1/chat/completions"
26-
tags: null
2722
composed:
28-
- id: "observe"
29-
description: null
30-
endpoint: []
31-
tags: null
32-
includes:
33-
- "readLogs"
3423
ztat:
3524
provider: "ztat-service.internal"
3625
ttl: "5m"

core/src/main/java/io/sentrius/sso/config/KeycloakManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import lombok.Builder;
77
import lombok.Getter;
88
import lombok.Setter;
9+
import lombok.extern.slf4j.Slf4j;
910
import org.keycloak.OAuth2Constants;
1011
import org.keycloak.admin.client.Keycloak;
1112
import org.keycloak.admin.client.KeycloakBuilder;
1213

1314
@Builder
1415
@Getter
1516
@Setter
17+
@Slf4j
1618
public class KeycloakManager {
1719
private Keycloak keycloak;
1820

@@ -29,6 +31,8 @@ public void addPublicKey(String kid, PublicKey publicKey) {
2931

3032

3133
public Keycloak createKeycloakClient(String serverUrl, String realm, String clientId, String clientSecret) {
34+
log.info("Creating Keycloak client for server: {}, realm: {}, clientId: {} shhh {}", serverUrl, realm,
35+
clientId, clientSecret);
3236
return KeycloakBuilder.builder()
3337
.serverUrl(serverUrl)
3438
.realm(realm)

core/src/main/java/io/sentrius/sso/core/dto/AgentRegistrationDTO.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ public class AgentRegistrationDTO {
1717
private final String agentPublicKey;
1818
private final String agentPublicKeyAlgo;
1919
private final String clientSecret;
20+
private final String clientId;
21+
private final String agentType;
2022
}

0 commit comments

Comments
 (0)