Add search Engine _ Onyphe#672
Conversation
|
""" WalkthroughThe changes introduce support for the Onyphe data source throughout the codebase. This includes implementing an Onyphe agent, integrating it into the provider and session management, adding command-line options, updating key handling, and providing integration tests. The system now supports querying Onyphe as a first-class engine alongside existing sources. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant Service
participant OnypheAgent
participant OnypheAPI
User->>CLI: Run with --engine onyphe or -on query
CLI->>Service: Initialize with Onyphe options
Service->>OnypheAgent: Query("google.com", API key)
OnypheAgent->>OnypheAPI: HTTP GET /api/v2/simple/port/{query}/{page}
OnypheAPI-->>OnypheAgent: JSON response (results)
OnypheAgent-->>Service: Stream results via channel
Service-->>CLI: Aggregate and return results
Assessment against linked issues
Poem
Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note ⚡️ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 30th. To opt out, configure 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (5)
integration-tests/source-test.go (1)
249-266: Implementation looks good, but consider using a more specific test query.The Onyphe test implementation follows the same pattern as other test cases, which is good for consistency. However, consider using a more specific query similar to other test cases (e.g., a targeted query like "'app=Grafana'" used in other tests) rather than the generic "google.com" to better validate the specific search capabilities of Onyphe.
sources/agent/onyphe/onyphe.go (4)
15-15: Consider moving URL components to separate constants for better maintainabilityThe URL template contains several hardcoded values that may require changes in the future. Breaking these into separate constants would improve clarity and maintainability.
-const ( - URLTemplate = "https://www.onyphe.io/api/v2/search/?q=%s&page=%d&size=10" -) +const ( + BaseURL = "https://www.onyphe.io/api/v2/search/" + DefaultPageSize = 10 + URLTemplate = BaseURL + "?q=%s&page=%d&size=" + fmt.Sprintf("%d", DefaultPageSize) +)
64-92: Add early return when limit is reachedTo avoid unnecessary API calls, check if the limit has been reached before processing each result.
func (agent *Agent) query(session *sources.Session, onypheRequest OnypheRequest, results chan sources.Result) *OnypheResponse { resp, err := agent.queryURL(session, &onypheRequest) if err != nil { results <- sources.Result{Source: agent.Name(), Error: err} return nil } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { results <- sources.Result{Source: agent.Name(), Error: err} return nil } var apiResponse OnypheResponse if err := json.Unmarshal(body, &apiResponse); err != nil { results <- sources.Result{Source: agent.Name(), Error: err} return nil } + // Check if API returned an error code + if apiResponse.Error != 0 { + results <- sources.Result{Source: agent.Name(), Error: fmt.Errorf("API returned error code: %d", apiResponse.Error)} + return nil + } + for _, result := range apiResponse.Results { results <- sources.Result{ Source: agent.Name(), IP: result.IP, Port: result.Port, } } return &apiResponse }
18-21: Consider adding comments to struct definitionAdding descriptive comments to the struct definition would improve code documentation and help future maintainers understand the purpose of each field.
+// OnypheRequest contains the parameters needed to query the Onyphe API type OnypheRequest struct { + // Query is the search term to look for Query string + // Page is the pagination parameter (1-based) Page int }
23-23: Add struct documentationThe Agent struct is currently undocumented. Adding a comment would improve code clarity.
+// Agent implements the sources.Agent interface for Onyphe type Agent struct{}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
sources/agent/onyphe/example.jsonis excluded by!**/*.json
📒 Files selected for processing (9)
integration-tests/integration-test.go(1 hunks)integration-tests/source-test.go(1 hunks)runner/options.go(7 hunks)sources/agent/onyphe/onyphe.go(1 hunks)sources/agent/onyphe/response.go(1 hunks)sources/keys.go(2 hunks)sources/provider.go(4 hunks)sources/session.go(1 hunks)uncover.go(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
uncover.go (2)
sources/agent/onyphe/onyphe.go (1)
Agent(23-23)sources/agent.go (1)
Agent(8-11)
sources/agent/onyphe/onyphe.go (6)
sources/agent.go (1)
Query(3-6)sources/session.go (1)
Session(37-42)sources/agent/onyphe/response.go (2)
Result(11-14)OnypheResponse(3-9)sources/keys.go (1)
Keys(3-22)uncover.go (1)
New(54-106)sources/util.go (1)
NewHTTPRequest(10-17)
🔇 Additional comments (10)
sources/session.go (1)
33-33: Rate limit for Onyphe API looks appropriateThe addition of Onyphe to the DefaultRateLimits map with a rate limit of 1 request per second is consistent with most other engines in the system and aligns with Onyphe's API requirements.
integration-tests/integration-test.go (1)
35-35: Integration test for Onyphe properly registeredThe Onyphe test cases are correctly added to the tests map, following the same pattern as other data sources in the integration test framework.
sources/keys.go (2)
21-21: Onyphe API key field properly addedThe OnypheKey field has been correctly added to the Keys struct to store the API key needed for authentication with the Onyphe service.
41-42: Empty() method correctly updatedThe Empty() method has been properly updated to include the check for the OnypheKey, ensuring the method accurately reports if any API keys are configured.
uncover.go (3)
19-19: Onyphe agent package import correctly addedThe import for the onyphe package is properly added to the imports list.
86-87: Onyphe agent properly integratedThe Onyphe agent is correctly instantiated and added to the service's Agents slice when "onyphe" is selected, following the same pattern as other agents.
192-192: Onyphe agent included in AllAgents()The "onyphe" engine is properly added to the list of all supported agents returned by the AllAgents() method.
runner/options.go (1)
62-62: Integration looks clean and consistent.The Onyphe engine has been properly added to all relevant parts of the options handling code:
- Added to the Options struct
- Included in the engine description list
- Added as a command-line flag with appropriate shorthand
- Included in all validation checks
- Added to the query appending logic
This approach maintains consistency with other engines in the codebase.
Also applies to: 74-74, 93-93, 167-167, 238-238, 264-264, 306-306
sources/provider.go (1)
37-37: Provider integration looks correct.The Onyphe provider has been properly added to all relevant parts of the provider:
- Added to the Provider struct for storing API keys
- Included in the key retrieval logic
- Added to the environment variable loading process
- Included in the HasKeys validation check
The implementation follows the established pattern for provider integration.
Also applies to: 120-122, 170-170, 189-189
sources/agent/onyphe/onyphe.go (1)
1-12: The API implementation looks good overallThe Onyphe agent implementation follows the existing pattern for other agents in the codebase. It correctly implements pagination, error handling, and API authentication.
| case "onyphe": | ||
| s.Agents = append(s.Agents, &onyphe.Agent{}) |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify the Agent implementation
While the agent integration looks correct, it would be beneficial to verify that the Onyphe agent properly implements the required interface methods and has appropriate error handling.
🏁 Script executed:
#!/bin/bash
# Verify that the Onyphe agent implements the required interface methods
# Check if the Onyphe agent implements the Name() method
echo "Checking for Name() method implementation:"
rg -A 2 "func \(\*?Agent\) Name\(\)" sources/agent/onyphe/
# Check if the Onyphe agent implements the Query() method
echo "Checking for Query() method implementation:"
rg -A 5 "func \(\*?Agent\) Query\(" sources/agent/onyphe/
# Check error handling in the Query method
echo "Checking error handling in Query method:"
rg "if err" -A 2 -B 2 sources/agent/onyphe/onyphe.goLength of output: 1152
🏁 Script executed:
#!/bin/bash
# Locate the Agent interface and its required methods
echo "Searching for Agent interface definition:"
rg -n "type .*Agent interface"
echo
echo "Context around Agent interface:"
rg -n -A5 -B5 "type .*Agent interface"
echo
echo "Searching for Name() method in interface files:"
rg -n "Name()" -g "*.go"
echo
echo "Searching for Query() method in interface files:"
rg -n "Query(" -g "*.go"Length of output: 9984
Implement missing Query() and standardize error handling
The Onyphe agent currently only exposes Name() but does not satisfy the Agent interface (which requires Query(*Session, *Query) (chan Result, error)) and its internal query helper returns errors instead of emitting them to the results channel.
Please update sources/agent/onyphe/onyphe.go as follows:
- Add the public Query method matching the interface in
sources/agent.go(lines 8–11):func (agent *Agent) Query(session *sources.Session, q *sources.Query) (chan sources.Result, error) { results := make(chan sources.Result) go func() { defer close(results) // translate sources.Query → OnypheRequest and invoke internal query agent.query(session, onypheReq, results) }() return results, nil }
- Unify error handling inside the internal query function so that every error is sent to results (rather than returning it):
request, err := sources.NewHTTPRequest(...)
- if err != nil {
- return nil, err
- }
- if err != nil {
- results <- sources.Result{Source: agent.Name(), Error: err}
- return nil
- }
With these changes the Onyphe agent will fully implement the interface and handle all errors consistently.
<!-- This is an auto-generated comment by CodeRabbit -->
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
sources/agent/onyphe/onyphe.go (1)
29-62: Implement support for query limit parameterThe
Querystruct fromsources/agent.gocontains aLimitfield, but this implementation doesn't use it. The agent should respect the user's requested limit on the number of results.func (agent *Agent) Query(session *sources.Session, query *sources.Query) (chan sources.Result, error) { if session.Keys.OnypheKey == "" { return nil, errors.New("empty Onyphe API key") } results := make(chan sources.Result) go func() { defer close(results) currentPage := 1 totalResults := 0 + maxResults := query.Limit for { onypheRequest := &OnypheRequest{ Query: query.Query, Page: currentPage, } apiResponse := agent.query(session, *onypheRequest, results) if apiResponse == nil { break } totalResults += len(apiResponse.Results) - if totalResults >= apiResponse.Total || len(apiResponse.Results) == 0 { + if totalResults >= apiResponse.Total || len(apiResponse.Results) == 0 || (maxResults > 0 && totalResults >= maxResults) { break } currentPage++ } }() return results, nil }
🧹 Nitpick comments (3)
sources/agent/onyphe/onyphe.go (3)
15-15: Consider making page size configurable instead of hardcodedThe URL template contains a hardcoded page size of 10. This might be better defined as a configurable constant to allow for flexibility in the number of results per page.
- URLTemplate = "https://www.onyphe.io/api/v2/search/?q=%s&page=%d&size=10" + DefaultPageSize = 10 + URLTemplate = "https://www.onyphe.io/api/v2/search/?q=%s&page=%d&size=%d"Then update the
queryURLmethod to use this constant.
84-90: Add validation for API response dataThe code doesn't validate that the response contains valid data before using it. Consider adding basic validation for the result fields before sending them to the results channel.
for _, result := range apiResponse.Results { + // Skip results with empty IP addresses + if result.IP == "" { + continue + } + results <- sources.Result{ Source: agent.Name(), IP: result.IP, Port: result.Port, } }
94-115: Ensure proper handling of API request errorsYour implementation now handles the basic HTTP status code errors, which is good. However, you might want to add more specific error handling for different status codes to give users better diagnostics.
if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + switch resp.StatusCode { + case http.StatusUnauthorized, http.StatusForbidden: + return nil, fmt.Errorf("authentication error: invalid API key or insufficient permissions (status code: %d)", resp.StatusCode) + case http.StatusTooManyRequests: + return nil, fmt.Errorf("rate limit exceeded (status code: %d)", resp.StatusCode) + default: + return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)
📒 Files selected for processing (1)
sources/agent/onyphe/onyphe.go(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
sources/agent/onyphe/onyphe.go (6)
sources/agent.go (1)
Query(3-6)sources/session.go (1)
Session(37-42)sources/agent/onyphe/response.go (2)
Result(11-14)OnypheResponse(3-9)sources/keys.go (1)
Keys(3-22)uncover.go (1)
New(54-106)sources/util.go (1)
NewHTTPRequest(10-17)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
@Xanderux Thanks for the PR! |
|
any advice @ehsandeep ? 😃 |
|
@Xanderux I forgot to mention it. Could you update the README to add this provider? Thanks! See https://github.com/projectdiscovery/uncover?tab=readme-ov-file#provider-configuration - Once it's done, we can merge this. |
done, sorry for the omission @dogancanbakir ;) |
Implement additional search engine that called Onyphe
If this code has some bug or improvements Please let me know in the comments
Ref: https://search.onyphe.io/
API docs: https://search.onyphe.io/docs/general-apis/search
Closes #196
Summary by CodeRabbit