Skip to content

set a user agent string#50

Open
mstanbCO wants to merge 2 commits intomainfrom
mstanbCO/set_user_agent_string
Open

set a user agent string#50
mstanbCO wants to merge 2 commits intomainfrom
mstanbCO/set_user_agent_string

Conversation

@mstanbCO
Copy link
Copy Markdown
Contributor

@mstanbCO mstanbCO commented Mar 4, 2026

Description

Set's the user agent string to conductorone-crowdstrike

Summary by CodeRabbit

  • Chores
    • Connector now includes the product version in CrowdStrike communications and identity protection requests (reflected in the User-Agent), improving traceability of requests.
    • Internal initialization updated to propagate version information through the connector and identity protection client; no changes to user-facing workflows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 4, 2026

📝 Walkthrough

Walkthrough

Connector and identity-protection clients now accept and propagate a version string; the CrowdStrike client/User-Agent is set from that version (conductorone-crowdstrike/%s). Call sites and builders were updated to pass the version through the initialization chain.

Changes

Cohort / File(s) Summary
Connector core
pkg/connector/connector.go, cmd/baton-crowdstrike/main.go
New constructor signature now accepts an additional version string parameter; call sites updated to pass version. The Connector stores the version and sets UserAgentOverride on the CrowdStrike client config.
Identity protection transport
pkg/connector/identity_protection.go
NewIdentityProtectionClient signature now accepts version string; transport struct gained userAgent field and RoundTrip sets User-Agent to conductorone-crowdstrike/<version> (dynamic).
Security insight builder
pkg/connector/security_insight.go
securityInsightBuilder gained a version parameter and passes it into NewIdentityProtectionClient, propagating version for IP client creation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I found a version on my hop today,
I tucked it into headers on the way,
conductorone now sings in UA bright,
Clients and builders carry it right,
A tiny change—yet everything’s okay 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: updating the user agent string from a hardcoded value to a dynamic version-based string across the connector implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mstanbCO/set_user_agent_string

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 4, 2026

Claude finished @mstanbCO's task in 30s —— View job


PR Review: Set User Agent String

  • Gather context and read changed files
  • Review code changes
  • Post review feedback

Review Summary

LGTM — This is a clean, straightforward change that standardizes the user agent string to conductorone-crowdstrike across both API clients.

Changes

  1. pkg/connector/connector.go — Adds UserAgentOverride: "conductorone-crowdstrike" to the Falcon SDK client config. This is the proper SDK-level way to set the user agent.

  2. pkg/connector/identity_protection.go — Updates the custom identityProtectionTransport from "baton-crowdstrike" to "conductorone-crowdstrike" to match.

Notes

  • Both API paths (Falcon SDK client and the identity protection GraphQL client) now use the same consistent user agent string.
  • No issues found with the implementation.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/connector/connector.go (1)

95-100: Optional: centralize the user-agent string in one package constant

Line 99 is correct for this PR. To avoid drift with Line 205 in pkg/connector/identity_protection.go, consider a shared constant.

Proposed refactor
 package connector

+const crowdStrikeUserAgent = "conductorone-crowdstrike"
+
 import (
 	"context"
 	"fmt"
@@
 	client, err := falcon.NewClient(&falcon.ApiConfig{
 		ClientId:          clientId,
 		ClientSecret:      clientSecret,
 		Cloud:             cloudRegion,
 		Context:           ctx,
-		UserAgentOverride: "conductorone-crowdstrike",
+		UserAgentOverride: crowdStrikeUserAgent,
 	})

And in pkg/connector/identity_protection.go:

-	req.Header.Set("User-Agent", "conductorone-crowdstrike")
+	req.Header.Set("User-Agent", crowdStrikeUserAgent)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/connector/connector.go` around lines 95 - 100, Create a package-level
constant for the shared user-agent string and replace the hardcoded
"conductorone-crowdstrike" occurrences with that constant; specifically add
something like const DefaultUserAgent = "conductorone-crowdstrike" in package
connector and update the Client construction's UserAgentOverride field (where
UserAgentOverride is set) and the usage in identity_protection.go (the other
occurrence at Line ~205) to reference DefaultUserAgent so both locations use the
single centralized symbol.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/connector/connector.go`:
- Around line 95-100: Create a package-level constant for the shared user-agent
string and replace the hardcoded "conductorone-crowdstrike" occurrences with
that constant; specifically add something like const DefaultUserAgent =
"conductorone-crowdstrike" in package connector and update the Client
construction's UserAgentOverride field (where UserAgentOverride is set) and the
usage in identity_protection.go (the other occurrence at Line ~205) to reference
DefaultUserAgent so both locations use the single centralized symbol.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 51fc068e-7470-42a2-bc80-8fea560e072e

📥 Commits

Reviewing files that changed from the base of the PR and between c7c5873 and 53b4f3a.

📒 Files selected for processing (2)
  • pkg/connector/connector.go
  • pkg/connector/identity_protection.go

@mstanbCO mstanbCO requested a review from a team March 4, 2026 18:00
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 4, 2026

Claude finished @mstanbCO's task in 49s —— View job


PR Review: Set User Agent String

  • Gather context and read changed files
  • Review code changes
  • Post review feedback

Review Summary

LGTM — Clean change that sets a versioned user agent string (conductorone-crowdstrike/<version>) across both API clients.

Changes

File Change
cmd/baton-crowdstrike/main.go Passes the build-time version variable into connector.New()
pkg/connector/connector.go Adds version field to Connector, sets UserAgentOverride on the Falcon SDK client with format conductorone-crowdstrike/<version>
pkg/connector/identity_protection.go Adds userAgent field to identityProtectionTransport, passes versioned user agent through from constructor
pkg/connector/security_insight.go Threads the version parameter through securityInsightBuilder to the identity protection client

Feedback

  1. Good: The version is now included in the user agent string (conductorone-crowdstrike/<version>), which is better than a bare string for debugging and API analytics.

  2. Good: Both API paths (Falcon SDK and identity protection GraphQL) use the same consistent format.

  3. Nitpick (optional): The user agent format string "conductorone-crowdstrike/%s" appears in two places (connector.go:98 and identity_protection.go:191). Consider extracting to a shared constant or helper to prevent drift:

    const userAgentPrefix = "conductorone-crowdstrike"
    
    func userAgent(version string) string {
        return fmt.Sprintf("%s/%s", userAgentPrefix, version)
    }

    This is minor and not blocking — the current approach is perfectly fine for two occurrences.

  4. Note: When version is the default "dev" (local builds), the user agent will be conductorone-crowdstrike/dev, which is reasonable.

No issues found. Approving.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
pkg/connector/connector.go (2)

102-104: ⚠️ Potential issue | 🟡 Minor

Add connector prefix to SDK init error message.

Line 103 wraps correctly with %w, but it should include the connector prefix for consistency with project rules.

Suggested patch
-		return nil, fmt.Errorf("failed to initialize SDK client: %w", err)
+		return nil, fmt.Errorf("baton-crowdstrike: failed to initialize SDK client: %w", err)

As per coding guidelines: "**/*.go: Always wrap errors with %w and include connector prefix (e.g., 'baton-service:') in error messages".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/connector/connector.go` around lines 102 - 104, The error return that
currently reads fmt.Errorf("failed to initialize SDK client: %w", err) must
include the connector prefix per project rules; update the error wrapping to
prepend the connector prefix (e.g., "connector:") so the returned error becomes
something like "connector: failed to initialize SDK client: %w" while still
using %w to wrap err—locate the fmt.Errorf(...) call in
pkg/connector/connector.go (the SDK init error return) and modify its message
accordingly.

17-23: ⚠️ Potential issue | 🔴 Critical

Implement Close() method on Connector to clean up HTTP client connections.

The Connector type in pkg/connector/connector.go is missing a Close() method. The connector initializes an HTTP client via falcon.NewClient() (line 95-104) which maintains persistent connection pools via CrowdStrikeAPISpecification.Transport. Without proper cleanup, these connections leak resources.

Add a Close() method that invokes CloseIdleConnections() on the underlying HTTP transport to release pooled connections. Return an error only if cleanup fails; do not return nil when clients exist.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/connector/connector.go` around lines 17 - 23, Add a Close method on the
Connector type that cleans up the HTTP client's persistent connections:
implement Connector.Close() to locate the underlying HTTP transport from the
Connector.client (the *fClient.CrowdStrikeAPISpecification returned by
falcon.NewClient()) and call CloseIdleConnections() on it; ensure the method
returns an error only if cleanup fails and otherwise returns nil, and safely
handle the case where Connector.client or its Transport is nil to avoid panics.
cmd/baton-crowdstrike/main.go (1)

20-66: ⚠️ Potential issue | 🔴 Critical

Add missing --base-url and --insecure configuration flags.

Both flags are required per coding guidelines but are not implemented. The configuration schema in pkg/config/config.go is missing BaseURLField and InsecureField definitions, and the connector.New() function in pkg/connector/connector.go does not accept these parameters. These flags are essential for mock server testing and supporting self-signed certificates in test scenarios.

  • Add BaseURLField and InsecureField to pkg/config/config.go
  • Add these fields to the Crowdstrike struct generated in pkg/config/conf.gen.go
  • Update connector.New() signature to accept baseURL and insecure parameters
  • Pass these values through to the underlying HTTP client configuration
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/baton-crowdstrike/main.go` around lines 20 - 66, Add missing BaseURLField
and InsecureField to the configuration schema (define BaseURLField and
InsecureField in the config schema), add matching fields to the Crowdstrike
struct in the generated conf (ensure Crowdstrike has BaseURL string and Insecure
bool), update connector.New(ctx, ...) signature to accept baseURL string and
insecure bool and propagate those args through to the HTTP client creation
inside connector.New so the underlying HTTP client uses the provided base URL
and toggles TLS verification for self-signed certs; update all call sites (e.g.,
getConnector) to pass cfg.BaseURL and cfg.Insecure into connector.New.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/connector/identity_protection.go`:
- Around line 202-207: The RoundTrip method on identityProtectionTransport
unconditionally sets the User-Agent header from t.userAgent, but RefreshContext
rebuilds the transport without initializing userAgent causing it to erase the
header; fix by preserving/initializing the value when the transport is rebuilt
(in RefreshContext) or change RoundTrip to only set the header when t.userAgent
is non-empty (e.g., check t.userAgent != "" before calling req.Header.Set).
Update the identityProtectionTransport construction logic to copy or pass
through the existing userAgent and ensure RefreshContext initializes
identityProtectionTransport.userAgent.

---

Outside diff comments:
In `@cmd/baton-crowdstrike/main.go`:
- Around line 20-66: Add missing BaseURLField and InsecureField to the
configuration schema (define BaseURLField and InsecureField in the config
schema), add matching fields to the Crowdstrike struct in the generated conf
(ensure Crowdstrike has BaseURL string and Insecure bool), update
connector.New(ctx, ...) signature to accept baseURL string and insecure bool and
propagate those args through to the HTTP client creation inside connector.New so
the underlying HTTP client uses the provided base URL and toggles TLS
verification for self-signed certs; update all call sites (e.g., getConnector)
to pass cfg.BaseURL and cfg.Insecure into connector.New.

In `@pkg/connector/connector.go`:
- Around line 102-104: The error return that currently reads fmt.Errorf("failed
to initialize SDK client: %w", err) must include the connector prefix per
project rules; update the error wrapping to prepend the connector prefix (e.g.,
"connector:") so the returned error becomes something like "connector: failed to
initialize SDK client: %w" while still using %w to wrap err—locate the
fmt.Errorf(...) call in pkg/connector/connector.go (the SDK init error return)
and modify its message accordingly.
- Around line 17-23: Add a Close method on the Connector type that cleans up the
HTTP client's persistent connections: implement Connector.Close() to locate the
underlying HTTP transport from the Connector.client (the
*fClient.CrowdStrikeAPISpecification returned by falcon.NewClient()) and call
CloseIdleConnections() on it; ensure the method returns an error only if cleanup
fails and otherwise returns nil, and safely handle the case where
Connector.client or its Transport is nil to avoid panics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2eb2e4c0-510f-4aca-95ee-2bfcc80c4e02

📥 Commits

Reviewing files that changed from the base of the PR and between 53b4f3a and acbc5d6.

📒 Files selected for processing (4)
  • cmd/baton-crowdstrike/main.go
  • pkg/connector/connector.go
  • pkg/connector/identity_protection.go
  • pkg/connector/security_insight.go

Comment on lines +202 to +207
base http.RoundTripper
userAgent string
}

func (t *identityProtectionTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("User-Agent", "baton-crowdstrike")
req.Header.Set("User-Agent", t.userAgent)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

User-Agent can be unintentionally cleared after RefreshContext().

Line 207 always sets User-Agent from t.userAgent, but RefreshContext() rebuilds transport without initializing userAgent, so it becomes empty and wipes the header.

Suggested patch
 type IdentityProtectionClient struct {
 	httpClient *http.Client
 	endpoint   string
+	userAgent  string
 }

 func NewIdentityProtectionClient(ctx context.Context, clientID, clientSecret, host, version string) *IdentityProtectionClient {
+	ua := fmt.Sprintf("conductorone-crowdstrike/%s", version)
 	// Create OAuth2 client credentials config
 	config := clientcredentials.Config{
 		ClientID:     clientID,
 		ClientSecret: clientSecret,
 		TokenURL:     "https://" + host + "/oauth2/token",
@@
 	// Wrap the transport to add user-agent header
 	httpClient.Transport = &identityProtectionTransport{
 		base:      httpClient.Transport,
-		userAgent: fmt.Sprintf("conductorone-crowdstrike/%s", version),
+		userAgent: ua,
 	}

 	return &IdentityProtectionClient{
 		httpClient: httpClient,
 		endpoint:   "https://" + host + "/identity-protection/combined/graphql/v1",
+		userAgent:  ua,
 	}
 }
@@
 func (c *IdentityProtectionClient) RefreshContext(ctx context.Context, clientID, clientSecret, host string) {
@@
 	httpClient.Transport = &identityProtectionTransport{
-		base: httpClient.Transport,
+		base:      httpClient.Transport,
+		userAgent: c.userAgent,
 	}
 	c.httpClient = httpClient
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/connector/identity_protection.go` around lines 202 - 207, The RoundTrip
method on identityProtectionTransport unconditionally sets the User-Agent header
from t.userAgent, but RefreshContext rebuilds the transport without initializing
userAgent causing it to erase the header; fix by preserving/initializing the
value when the transport is rebuilt (in RefreshContext) or change RoundTrip to
only set the header when t.userAgent is non-empty (e.g., check t.userAgent != ""
before calling req.Header.Set). Update the identityProtectionTransport
construction logic to copy or pass through the existing userAgent and ensure
RefreshContext initializes identityProtectionTransport.userAgent.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant