From 1406c57eec4a362c6951b9cb2e8e656f9b038b2e Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 17 Oct 2025 16:22:41 +0900 Subject: [PATCH] Send User-Agent to DWS --- workhorse/_support/lint_last_known_acceptable.txt | 2 +- workhorse/internal/ai_assist/duoworkflow/client.go | 5 ++++- workhorse/internal/ai_assist/duoworkflow/client_test.go | 2 +- workhorse/internal/ai_assist/duoworkflow/runner.go | 4 +++- workhorse/internal/version/version.go | 5 +++++ workhorse/internal/version/version_test.go | 8 ++++++++ 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/workhorse/_support/lint_last_known_acceptable.txt b/workhorse/_support/lint_last_known_acceptable.txt index 7c9dfd1e3d7a4c..d1b7a9edc475ee 100644 --- a/workhorse/_support/lint_last_known_acceptable.txt +++ b/workhorse/_support/lint_last_known_acceptable.txt @@ -26,7 +26,7 @@ internal/git/error.go:38:4: singleCaseSwitch: should rewrite switch statement to cmd/gitlab-workhorse/main.go:315:10: G112: Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server (gosec) internal/ai_assist/duoworkflow/actions.go:92:42: G115: integer overflow conversion int -> int32 (gosec) internal/ai_assist/duoworkflow/actions.go:102:24: G115: integer overflow conversion int -> int32 (gosec) -internal/ai_assist/duoworkflow/client.go:56:73: G402: TLS MinVersion too low. (gosec) +internal/ai_assist/duoworkflow/client.go:59:73: G402: TLS MinVersion too low. (gosec) internal/api/channel_settings.go:57:28: G402: TLS MinVersion too low. (gosec) internal/config/config.go:293:18: G204: Subprocess launched with variable (gosec) internal/config/config.go:418:8: G101: Potential hardcoded credentials (gosec) diff --git a/workhorse/internal/ai_assist/duoworkflow/client.go b/workhorse/internal/ai_assist/duoworkflow/client.go index 38dccfec9a348e..130a85162c8ffd 100644 --- a/workhorse/internal/ai_assist/duoworkflow/client.go +++ b/workhorse/internal/ai_assist/duoworkflow/client.go @@ -18,6 +18,8 @@ import ( pb "gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/clients/gopb/contract" "google.golang.org/grpc" + "gitlab.com/gitlab-org/gitlab/workhorse/internal/version" + grpccorrelation "gitlab.com/gitlab-org/labkit/correlation/grpc" grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc" ) @@ -37,7 +39,7 @@ type Client struct { // NewClient creates a new Duo Workflow client with the specified server address, // headers, and security settings. -func NewClient(serverURI string, headers map[string]string, secure bool) (*Client, error) { +func NewClient(serverURI string, headers map[string]string, secure bool, userAgent string) (*Client, error) { opts := []grpc.DialOption{ grpc.WithKeepaliveParams(keepalive.ClientParameters{ Time: 20 * time.Second, // send pings every 20 seconds if there is no activity @@ -50,6 +52,7 @@ func NewClient(serverURI string, headers map[string]string, secure bool) (*Clien grpccorrelation.WithClientName("gitlab-duo-workflow"), ), ), + grpc.WithUserAgent(fmt.Sprintf("%s %s", userAgent, version.GetUserAgentShort())), } if secure { diff --git a/workhorse/internal/ai_assist/duoworkflow/client_test.go b/workhorse/internal/ai_assist/duoworkflow/client_test.go index a6105f322dc067..cc2c6688b301b4 100644 --- a/workhorse/internal/ai_assist/duoworkflow/client_test.go +++ b/workhorse/internal/ai_assist/duoworkflow/client_test.go @@ -116,7 +116,7 @@ func TestExecuteWorkflow(t *testing.T) { } func createTestClient(t *testing.T, server *testServer) *Client { - client, err := NewClient(server.Addr, map[string]string{"test": "header"}, false) + client, err := NewClient(server.Addr, map[string]string{"test": "header"}, false, "visual-studio-code/0.0.1") require.NoError(t, err) t.Cleanup(func() { _ = client.Close() }) return client diff --git a/workhorse/internal/ai_assist/duoworkflow/runner.go b/workhorse/internal/ai_assist/duoworkflow/runner.go index c6082069a6b2d9..bb4ba461941d99 100644 --- a/workhorse/internal/ai_assist/duoworkflow/runner.go +++ b/workhorse/internal/ai_assist/duoworkflow/runner.go @@ -58,7 +58,9 @@ type runner struct { } func newRunner(conn websocketConn, rails *api.API, r *http.Request, cfg *api.DuoWorkflow) (*runner, error) { - client, err := NewClient(cfg.ServiceURI, cfg.Headers, cfg.Secure) + userAgent := r.Header.Get("User-Agent") + + client, err := NewClient(cfg.ServiceURI, cfg.Headers, cfg.Secure, userAgent) if err != nil { return nil, fmt.Errorf("failed to initialize client: %v", err) } diff --git a/workhorse/internal/version/version.go b/workhorse/internal/version/version.go index fdf13d3cac42e5..5599f6872dd5f1 100644 --- a/workhorse/internal/version/version.go +++ b/workhorse/internal/version/version.go @@ -22,3 +22,8 @@ func GetUserAgent() string { func GetApplicationVersion() string { return fmt.Sprintf(schema, version, build) } + +// GetUserAgentShort returns short version of User-Agent +func GetUserAgentShort() string { + return fmt.Sprintf("gitlab-workhorse/%s", version) +} diff --git a/workhorse/internal/version/version_test.go b/workhorse/internal/version/version_test.go index f565dd76fa969d..e081669c1197cc 100644 --- a/workhorse/internal/version/version_test.go +++ b/workhorse/internal/version/version_test.go @@ -17,3 +17,11 @@ func TestVersion(t *testing.T) { require.Equal(t, "gitlab-workhorse ()-(123.123)", GetApplicationVersion()) } + +func TestVersionShort(t *testing.T) { + require.Equal(t, "gitlab-workhorse/", GetUserAgentShort()) + + SetVersion("15.3", "123.123") + + require.Equal(t, "gitlab-workhorse/15.3", GetUserAgentShort()) +} -- GitLab