Skip to content

Conversation

@gmjehovich
Copy link
Contributor

Add audit log assertions to RemoteClusterSecurityCrossClusterApiKeySigningIT.

@gmjehovich gmjehovich added Team:Security Meta label for security team :Security/Security Security issues without another label >enhancement labels Oct 27, 2025
@elasticsearchmachine
Copy link
Collaborator

Hi @gmjehovich, I've created a changelog YAML for you.

@gmjehovich gmjehovich requested a review from jfreden October 28, 2025 00:02
@gmjehovich gmjehovich marked this pull request as ready for review October 28, 2025 00:02
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-security (Team:Security)

Copy link
Contributor

@jfreden jfreden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this PR was made from your forks main branch. It might make it difficult to work on other stuff so I'd suggest opening a new PR from a branch.

throw new UncheckedIOException(e);
}
}
}, 10, java.util.concurrent.TimeUnit.SECONDS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can drop 10, java.util.concurrent.TimeUnit.SECONDS since that's the default.

@@ -0,0 +1,5 @@
pr: 137225
summary: Add audit log assertions to `RemoteClusterSecurityCrossClusterApiKeySi…`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like both the title and this was truncated.

}
}

private void assertCrossClusterSearchSuccessfulWithoutResult() throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also do some audit logging on the fulfilling cluster since the auth fails, the only difference here is that the query cluster ignores the problem.


try {
// Call the generic assertion function with the expected 'authentication_success' event
assertAuditLogContainsNewEvent(startTimeMillis, "authentication_success");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are constants for authentication_success and authentication_failed in AuditLevel that would be nice to use here.

assertAuditLogContainsNewEvent(startTimeMillis, "authentication_success");
} catch (Exception e) {
// Re-throw the exception so the test fails if the log isn't found
throw new RuntimeException("Audit log assertion failed after client-side success check passed.", e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a little confusing because I don't think the AssertionError thrown by assertAuditLogContainsNewEvent would be caught here (since it doesn't extend Exception). This would catch the IOException thrown by Stream.readAllLines. If readAllLines fail, I think failing the test with fail(e, msg) is better.

equalTo(true)
);
} catch (IOException e) {
throw new UncheckedIOException(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this happen in the test? Why not just throws IOException on the method instead?

return client().performRequest(request);
}

private String extractJsonValue(String jsonLine, String fieldName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this custom json logic I think it would be cleaner to use XContentHelper.convertToMap and also the constants from here. It will make the test easier to maintain.

private long parseLogTimestamp(String timestamp) {
try {
String standardized = timestamp.replace(',', '.');
java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuditIT has some code to do this, I wonder if that can be reused? See executeAndVerifyAudit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be possible to move it into a shared utility method, but I think the code there does more testing than we would need (extra assertions for each field, since it's testing general audit logging).

I went ahead and copied the date/time pattern used there. Let me know if that is sufficient, or if you think I should try to extract more shared logic to a utility

try (var auditLog = fulfillingCluster.getNodeLog(i, LogType.AUDIT)) {
final List<String> allLines = Streams.readAllLines(auditLog);

String expectedLogFragment = "event.action\":\"" + eventAction + "\"";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to use the constants from here to match against.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>enhancement :Security/Security Security issues without another label Team:Security Meta label for security team v9.3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants