Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom log type implementation #500

Merged
merged 1 commit into from
Jul 29, 2023

Conversation

sbcd90
Copy link
Collaborator

@sbcd90 sbcd90 commented Jul 26, 2023

Description

  • Refactor code to remove static DetectorType enum & make logtype dynamic.
  • Add api support for CRUD workflow of log types.

Issues Resolved

#447

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@codecov
Copy link

codecov bot commented Jul 26, 2023

Codecov Report

Merging #500 (10f5bf1) into 2.x (22b5fc9) will decrease coverage by 2.21%.
The diff coverage is 2.87%.

❗ Current head 10f5bf1 differs from pull request most recent head 1962c0e. Consider uploading reports for the commit 1962c0e to get more accurate results

@@             Coverage Diff              @@
##                2.x     #500      +/-   ##
============================================
- Coverage     28.16%   25.96%   -2.21%     
- Complexity      935      940       +5     
============================================
  Files           236      252      +16     
  Lines          9866    10687     +821     
  Branches       1118     1187      +69     
============================================
- Hits           2779     2775       -4     
- Misses         6844     7666     +822     
- Partials        243      246       +3     
Files Changed Coverage Δ
...rch/securityanalytics/SecurityAnalyticsPlugin.java 2.50% <0.00%> (-0.07%) ⬇️
...rityanalytics/action/CorrelatedFindingRequest.java 0.00% <0.00%> (ø)
...ityanalytics/action/DeleteCustomLogTypeAction.java 0.00% <0.00%> (ø)
...tyanalytics/action/DeleteCustomLogTypeRequest.java 0.00% <0.00%> (ø)
...yanalytics/action/DeleteCustomLogTypeResponse.java 0.00% <0.00%> (ø)
...rityanalytics/action/IndexCustomLogTypeAction.java 0.00% <0.00%> (ø)
...ityanalytics/action/IndexCustomLogTypeRequest.java 0.00% <0.00%> (ø)
...tyanalytics/action/IndexCustomLogTypeResponse.java 0.00% <0.00%> (ø)
...ityanalytics/action/SearchCustomLogTypeAction.java 0.00% <0.00%> (ø)
...tyanalytics/action/SearchCustomLogTypeRequest.java 0.00% <0.00%> (ø)
... and 21 more

@sbcd90 sbcd90 force-pushed the custom_log_type branch 4 times, most recently from 1ddbbff to deb0ae3 Compare July 28, 2023 01:40
@@ -133,15 +134,16 @@ public void onResponse(MultiSearchResponse items) {
for (int i = 0; i < 100; ++i) {
corrVector[i] = ((float) counter) - 50.0f;
}
corrVector[Detector.DetectorType.valueOf(detectorType.toUpperCase(Locale.ROOT)).getDim()] = (float) counter;

corrVector[Integer.parseInt(logTypes.get(detectorType).getTags().get("correlation_id").toString())] = (float) counter;
Copy link
Member

Choose a reason for hiding this comment

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

Can we break up Integer.parseInt(logTypes.get(detectorType).getTags().get("correlation_id").toString()) into variables and pass in the final variable here?

Copy link
Member

@lezzago lezzago Jul 28, 2023

Choose a reason for hiding this comment

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

It would be helpful for line 146, 163, 164 as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed it.

@@ -268,15 +270,15 @@ public void onResponse(IndexResponse response) {
if (response.status().equals(RestStatus.OK)) {
try {
float[] corrVector = new float[101];
corrVector[Detector.DetectorType.valueOf(detectorType.toUpperCase(Locale.ROOT)).getDim()] = 50.0f;
corrVector[Integer.parseInt(logTypes.get(detectorType).getTags().get("correlation_id").toString())] = 50.0f;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment as above about breaking it up into readable variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed it.

Map<String, Object> tags = logTypes.get(detectorType).getTags();
String correlationId = tags.get("correlation_id").toString();

protected List<CustomLogType> loadBuiltinLogTypesMetadata() throws URISyntaxException, IOException {
List<CustomLogType> customLogTypes = new ArrayList<>();

final String url = Objects.requireNonNull(BuiltinLogTypeLoader.class.getClassLoader().getResource(BASE_PATH)).toURI().toString();
Copy link
Member

Choose a reason for hiding this comment

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

We should have an exception message added as part of the requireNonNull function

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed it.


final String url = Objects.requireNonNull(BuiltinLogTypeLoader.class.getClassLoader().getResource(BASE_PATH)).toURI().toString();
Path dirPath = null;
if (url.contains("!")) {
Copy link
Member

Choose a reason for hiding this comment

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

Why would a url contain !?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the url contains ! because the plugin is loaded as a zip file.

}

Stream<Path> folder = Files.list(dirPath);
Path logTypePath = folder.filter(e -> e.toString().endsWith("logtypes.json")).collect(Collectors.toList()).get(0);
Copy link
Member

Choose a reason for hiding this comment

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

Do we know for a fact that we will get a folder that ends with logtypes.json to prevent array out of bounds type exception?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.fetchSource(true);
searchSourceBuilder.size(10000);
Copy link
Member

@lezzago lezzago Jul 28, 2023

Choose a reason for hiding this comment

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

Cant we use size 0 if we just want to see if it exists and use TotalHits?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

we add a filter clause to the query

                    .must(QueryBuilders.matchQuery("name", logType));```
so, it anyway will fetch `1 or 0` doc.  

Copy link
Member

Choose a reason for hiding this comment

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

why specify this then? It implies there can be a lot of results and may add confusion for other devs looking at it.

@@ -128,6 +134,92 @@ public void getAllLogTypes(ActionListener<List<String>> listener) {
}, listener::onFailure));
}

public void getAllLogTypesMetadata(ActionListener<List<String>> listener) {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to paginate? What happens if ther are more than 10000 documents?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

currently, we have only 13 predefined log types & we dont expect to grow to 10000 log types ever. so, it looks to be a good threshold.
we may add a setting in future on no. of allowed log types.

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.fetchSource(true);
searchSourceBuilder.size(10000);
Copy link
Member

Choose a reason for hiding this comment

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

do we need to paginate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the same logic applies here as we have only 13 pre-defined log sources. it is hard that no. of custom log types may go beyond 100.

@@ -438,7 +438,7 @@ private Object convertValueCidr(SigmaCIDRExpression ip) {
}

private String getMappedField(String field) {
if (this.enableFieldMappings && this.fieldMappings.containsKey(field)) {
if (this.enableFieldMappings && this.fieldMappings.containsKey(field) && this.fieldMappings.get(field) != null) {
Copy link
Member

Choose a reason for hiding this comment

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

If it contains the key, how would the value be set to null?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

there is a scenario when we create & then update a custom log type, we end up with fields which have only raw fields & no ecs fields.
this scenario is covered by integ test

public void testEditACustomLogTypeDescription() throws IOException {

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.fetchSource(true);
searchSourceBuilder.size(10000);
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to paginate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

same logic as #500 (comment)

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.fetchSource(true);
searchSourceBuilder.size(10000);
Copy link
Member

Choose a reason for hiding this comment

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

same question about pagination

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the same logic as #500 (comment).
it will be good to add a setting in future on max. no. of log types allowed. created issue here: #501

@sbcd90 sbcd90 force-pushed the custom_log_type branch from 53a7865 to 1962c0e Compare July 28, 2023 20:59
User user = readUserFromThreadContext(this.threadPool);

String validateBackendRoleMessage = validateUserBackendRoles(user, this.filterByEnabled);
if (!"".equals(validateBackendRoleMessage)) {
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: validateBackendRoleMessage.isNotEmpty()


public void onCreateMappingsResponse(CreateIndexResponse response) {
if (response.isAcknowledged()) {
log.info(String.format(Locale.getDefault(), "Created %s with mappings.", LogTypeService.LOG_TYPE_INDEX));
Copy link
Member

@lezzago lezzago Jul 28, 2023

Choose a reason for hiding this comment

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

Should this be a debug log? Same with the others.

Comment on lines +237 to +239
if (response.isTimedOut()) {
onFailures(new OpenSearchStatusException(String.format(Locale.getDefault(), "Log Type with id %s cannot be updated", logTypeId), RestStatus.INTERNAL_SERVER_ERROR));
return;
Copy link
Member

Choose a reason for hiding this comment

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

Does this happen often enough? If we are specifically looking for this, we should mention it timed out in the exception. Also this should not be an internal server error since this should be a a transient error that the customer can retry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sure. we need to address this in entire codebase. we'll do it in 2.10.
created an issue: #502

}
}

private void finishHim(CustomLogType logType, Exception... t) {
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Do we need to update the schema version?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this file is introduced in 2.9 open source release. so, we can keep schema version same.

Copy link
Member

@getsaurabh02 getsaurabh02 left a comment

Choose a reason for hiding this comment

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

LGTM

@sbcd90 sbcd90 merged commit ef64f00 into opensearch-project:2.x Jul 29, 2023
opensearch-trigger-bot bot pushed a commit that referenced this pull request Jul 29, 2023
Signed-off-by: Subhobrata Dey <[email protected]>
(cherry picked from commit ef64f00)
opensearch-trigger-bot bot pushed a commit that referenced this pull request Jul 29, 2023
Signed-off-by: Subhobrata Dey <[email protected]>
(cherry picked from commit ef64f00)
sbcd90 pushed a commit that referenced this pull request Jul 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants