fix(test): add required environmentId to agent register bodies
Registration now requires environmentId in the body (400 if missing), so the stale register bodies were failing every downstream test that relied on a registered agent. Affected helpers in: - BootstrapTokenIT (static constant + inline body) - JwtRefreshIT (registerAndGetTokens) - RegistrationSecurityIT (registerAgent) - SseSigningIT (registerAgentWithAuth) - AgentSseControllerIT (registerAgent helper) Also in JwtRefreshIT / RegistrationSecurityIT, the "access token can reach a protected endpoint" tests were hitting env-scoped read endpoints that now require VIEWER+. Redirected both to the AGENT-role heartbeat endpoint — it proves the token is accepted by the security filter without being coupled to RBAC rules for reader endpoints. JwtRefreshIT.refreshWithValidToken also dropped an isNotEqualTo assertion that assumed sub-second iat uniqueness — HMAC JWTs with second-precision claims are byte-identical when minted for the same subject within the same second, so the old assertion was flaky by design. SseSigningIT / AgentSseControllerIT still have SSE-connection timing failures unrelated to registration — parked separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,7 @@ class AgentSseControllerIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "%s",
|
"instanceId": "%s",
|
||||||
"applicationId": "%s",
|
"applicationId": "%s",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": ["route-1"],
|
"routeIds": ["route-1"],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class BootstrapTokenIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "bootstrap-test-agent",
|
"instanceId": "bootstrap-test-agent",
|
||||||
"applicationId": "test-group",
|
"applicationId": "test-group",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": [],
|
"routeIds": [],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
@@ -96,6 +97,7 @@ class BootstrapTokenIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "bootstrap-test-previous",
|
"instanceId": "bootstrap-test-previous",
|
||||||
"applicationId": "test-group",
|
"applicationId": "test-group",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": [],
|
"routeIds": [],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class JwtRefreshIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "%s",
|
"instanceId": "%s",
|
||||||
"applicationId": "test-group",
|
"applicationId": "test-group",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": [],
|
"routeIds": [],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
@@ -79,7 +80,9 @@ class JwtRefreshIT extends AbstractPostgresIT {
|
|||||||
JsonNode body = objectMapper.readTree(response.getBody());
|
JsonNode body = objectMapper.readTree(response.getBody());
|
||||||
assertThat(body.get("accessToken").asText()).isNotEmpty();
|
assertThat(body.get("accessToken").asText()).isNotEmpty();
|
||||||
assertThat(body.get("refreshToken").asText()).isNotEmpty();
|
assertThat(body.get("refreshToken").asText()).isNotEmpty();
|
||||||
assertThat(body.get("refreshToken").asText()).isNotEqualTo(refreshToken);
|
// NB: HMAC JWTs with second-precision iat/exp are byte-identical when
|
||||||
|
// minted for the same subject+claims within the same second, so we
|
||||||
|
// do not assert the new token differs from the old one.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -154,14 +157,15 @@ class JwtRefreshIT extends AbstractPostgresIT {
|
|||||||
JsonNode refreshBody2 = objectMapper.readTree(refreshResponse.getBody());
|
JsonNode refreshBody2 = objectMapper.readTree(refreshResponse.getBody());
|
||||||
String newAccessToken = refreshBody2.get("accessToken").asText();
|
String newAccessToken = refreshBody2.get("accessToken").asText();
|
||||||
|
|
||||||
// Use the new access token to hit a protected endpoint accessible by AGENT role
|
// Use the new access token to hit an AGENT-role endpoint (heartbeat) to
|
||||||
|
// verify the token is accepted by Spring Security. Env-scoped read
|
||||||
|
// endpoints now require VIEWER+, so an agent token would get 403 there.
|
||||||
HttpHeaders authHeaders = new HttpHeaders();
|
HttpHeaders authHeaders = new HttpHeaders();
|
||||||
authHeaders.set("Authorization", "Bearer " + newAccessToken);
|
authHeaders.set("Authorization", "Bearer " + newAccessToken);
|
||||||
authHeaders.set("X-Cameleer-Protocol-Version", "1");
|
authHeaders.set("X-Cameleer-Protocol-Version", "1");
|
||||||
|
|
||||||
ResponseEntity<String> response = restTemplate.exchange(
|
ResponseEntity<String> response = restTemplate.postForEntity(
|
||||||
"/api/v1/environments/default/executions",
|
"/api/v1/agents/refresh-access-test/heartbeat",
|
||||||
HttpMethod.GET,
|
|
||||||
new HttpEntity<>(authHeaders),
|
new HttpEntity<>(authHeaders),
|
||||||
String.class);
|
String.class);
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class RegistrationSecurityIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "%s",
|
"instanceId": "%s",
|
||||||
"applicationId": "test-group",
|
"applicationId": "test-group",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": [],
|
"routeIds": [],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
@@ -80,14 +81,15 @@ class RegistrationSecurityIT extends AbstractPostgresIT {
|
|||||||
JsonNode regBody = objectMapper.readTree(regResponse.getBody());
|
JsonNode regBody = objectMapper.readTree(regResponse.getBody());
|
||||||
String accessToken = regBody.get("accessToken").asText();
|
String accessToken = regBody.get("accessToken").asText();
|
||||||
|
|
||||||
// Use the access token to hit a protected endpoint accessible by AGENT role
|
// Hit an AGENT-role endpoint (heartbeat) to verify the access token is
|
||||||
|
// accepted. Env-scoped read endpoints now require VIEWER+, so the agent
|
||||||
|
// token would get 403 there.
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.set("Authorization", "Bearer " + accessToken);
|
headers.set("Authorization", "Bearer " + accessToken);
|
||||||
headers.set("X-Cameleer-Protocol-Version", "1");
|
headers.set("X-Cameleer-Protocol-Version", "1");
|
||||||
|
|
||||||
ResponseEntity<String> response = restTemplate.exchange(
|
ResponseEntity<String> response = restTemplate.postForEntity(
|
||||||
"/api/v1/environments/default/executions",
|
"/api/v1/agents/reg-sec-access-test/heartbeat",
|
||||||
HttpMethod.GET,
|
|
||||||
new HttpEntity<>(headers),
|
new HttpEntity<>(headers),
|
||||||
String.class);
|
String.class);
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ class SseSigningIT extends AbstractPostgresIT {
|
|||||||
{
|
{
|
||||||
"instanceId": "%s",
|
"instanceId": "%s",
|
||||||
"applicationId": "test-group",
|
"applicationId": "test-group",
|
||||||
|
"environmentId": "default",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"routeIds": ["route-1"],
|
"routeIds": ["route-1"],
|
||||||
"capabilities": {}
|
"capabilities": {}
|
||||||
|
|||||||
Reference in New Issue
Block a user