Add parser validation APIs and log-type CLI commands#201
Add parser validation APIs and log-type CLI commands#201ishree-dev wants to merge 1 commit intogoogle:mainfrom
Conversation
src/secops/chronicle/client.py
Outdated
| archived=archived, | ||
| run_frequency=run_frequency, | ||
| ) | ||
|
|
| raise SecOpsError(f"No parsers found for log type: {log_type}") | ||
|
|
||
| # Use the first parser's name (which includes the UUID) | ||
| parser_name = parsers_data["parsers"][0]["name"] |
There was a problem hiding this comment.
This may lead to null pointer exception. You're only checking if parsers field is present or not. It may be present and emtpy.
| raise SecOpsError(f"No parsers found for log type: {log_type}") | ||
|
|
||
| # Use the first parser's name (which includes the UUID) | ||
| parser_name = parsers_data["parsers"][0]["name"] |
There was a problem hiding this comment.
What's the logic to choose the first parser among multiple?
There was a problem hiding this comment.
multiple isnt supported right?
There was a problem hiding this comment.
Are we letting the user know about that any how? We should add a log that multiple parsers are not supported if there are instead of directly choosing the first.
| APIError: If the API request fails. | ||
| """ | ||
| instance_id = client.instance_id | ||
| if customer_id and customer_id != client.customer_id: |
There was a problem hiding this comment.
Can we initialize the client itself with the correct customer id if you're anyway getting it in the argument?
There was a problem hiding this comment.
Check if the customer id is already available via the gcloud auth command. In that case no need to provide the customer id separately.
| # First get the list of parsers for this log_type to find a valid | ||
| # parser UUID | ||
| parsers_url = f"{base_url}/{instance_id}/logTypes/{log_type}/parsers" | ||
| parsers_resp = client.session.get(parsers_url, timeout=timeout) |
There was a problem hiding this comment.
Can't we use the some information from metadata.json file instead of fetching the parsers for this logtype and then using the first available name?
There was a problem hiding this comment.
we are expecting log_type from the cli command
| ) | ||
|
|
||
| parsers_data = parsers_resp.json() | ||
| if not parsers_data.get("parsers"): |
There was a problem hiding this comment.
If no parser exists for that log type, why are we not triggering the github check api?
src/secops/cli/commands/log_type.py
Outdated
| result = chronicle.get_analysis_report(name=args.name) | ||
| output_formatter(result, args.output) | ||
| except APIError as e: | ||
| print(f"API error: {e}", file=sys.stderr) |
| except APIError as e: | ||
| print(f"API error: {e}", file=sys.stderr) | ||
| sys.exit(1) | ||
| except SecOpsError as e: |
There was a problem hiding this comment.
When will this error come?
There was a problem hiding this comment.
This SecOpsError is caught because chronicle.get_analysis_report(name=args.name) performs local input validation before sending the request. If the user passes an empty or invalid name
(e.g., less than 5 characters long), the internal client method raises a SecOpsError rather than an APIError.
|
|
||
| result = mock_client.trigger_github_checks( | ||
| associated_pr="owner/repo/pull/123", | ||
| log_type="BRO_DNS", |
There was a problem hiding this comment.
Replace this with DUMMY_LOGTYPE
tests/cli/test_log_type.py
Outdated
| """Test successful trigger_checks command execution.""" | ||
| args = Namespace( | ||
| associated_pr="owner/repo/pull/123", | ||
| log_type="BRO_DNS", |
| "log-type", | ||
| "trigger-checks", | ||
| "--associated-pr", | ||
| "google/secops-wrapper/pull/1", |
There was a problem hiding this comment.
Why choose the 1st PR? Is that related to this project?
There was a problem hiding this comment.
this is a sample pr, can be any number
1172e71 to
a119b36
Compare
| if not isinstance(log_type, str) or len(log_type.strip()) < 2: | ||
| raise SecOpsError("log_type must be a valid string of length >= 2") | ||
| if customer_id is not None: | ||
| if not isinstance(customer_id, str) or len(customer_id.strip()) < 2: |
There was a problem hiding this comment.
Lets use pattern matching for Customer Id as its a UUID
|
|
||
| def trigger_github_checks( | ||
| client: "ChronicleClient", | ||
| associated_pr: str, |
There was a problem hiding this comment.
Lets add proper validations for the structure of this string, validate by breaking the path and number of substrings, valid pr number.
| # First get the list of parsers for this log_type to find a valid | ||
| # parser UUID | ||
| parsers_url = f"{base_url}/{instance_id}/logTypes/{log_type}/parsers" | ||
| parsers_resp = client.session.get(parsers_url, timeout=timeout) |
This PR introduces new SDK wrapper methods and CLI commands for Chronicle Parser Validation tooling. It specifically adds functionality to trigger GitHub checks for parsers and retrieve their corresponding analysis reports.
Key Changes:
New SDK Methods (src/secops/chronicle/client.py & parser_validation.py):
trigger_github_checks: Triggers a parser analysis report against an associated GitHub PR.
get_analysis_report: Retrieves a completed parser analysis report using its full resource name.
New CLI Commands (src/secops/cli/commands/log_type.py):
Testing (tests/):
Documentation:
Updated api_module_mapping.md to map logTypes.triggerGitHubChecks and logTypes.getParserAnalysisReport to their respective CLI counterparts.