From 925e7ba0f8ca3b170b3ec6fb1555a107c3df21f9 Mon Sep 17 00:00:00 2001 From: Juan Antonio Osorio Date: Thu, 9 Nov 2023 12:31:12 +0200 Subject: [PATCH] Add enhanced user agent informtion to CLI (#1600) This replicates the user agent format that browsers use in order to get more relevant debugging information without revealing any PII. --- cmd/cli/app/version/version.go | 2 ++ internal/constants/version.go | 2 +- internal/util/cli/useragent/useragent.go | 46 ++++++++++++++++++++++++ internal/util/helpers.go | 22 ++++++++---- 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 internal/util/cli/useragent/useragent.go diff --git a/cmd/cli/app/version/version.go b/cmd/cli/app/version/version.go index 66e19c3b4f..0cc64394a2 100644 --- a/cmd/cli/app/version/version.go +++ b/cmd/cli/app/version/version.go @@ -22,6 +22,7 @@ import ( "github.com/stacklok/minder/cmd/cli/app" "github.com/stacklok/minder/internal/constants" "github.com/stacklok/minder/internal/util/cli" + "github.com/stacklok/minder/internal/util/cli/useragent" ) // VersionCmd is the version command @@ -31,6 +32,7 @@ var VersionCmd = &cobra.Command{ Long: `The minder version command prints the version of the minder CLI.`, Run: func(cmd *cobra.Command, _ []string) { cli.PrintCmd(cmd, constants.VerboseCLIVersion) + cli.PrintCmd(cmd, "User Agent: %s", useragent.GetUserAgent()) }, } diff --git a/internal/constants/version.go b/internal/constants/version.go index 66267bef96..5058e1c1c0 100644 --- a/internal/constants/version.go +++ b/internal/constants/version.go @@ -44,7 +44,7 @@ const ( verboseTemplate = `Version: {{.Version}} Go Version: {{.GoVersion}} Git Commit: {{.Commit}} -Built: {{.Time}} +Commit Date: {{.Time}} OS/Arch: {{.OS}}/{{.Arch}} Dirty: {{.Modified}}` ) diff --git a/internal/util/cli/useragent/useragent.go b/internal/util/cli/useragent/useragent.go new file mode 100644 index 0000000000..c02220422b --- /dev/null +++ b/internal/util/cli/useragent/useragent.go @@ -0,0 +1,46 @@ +// +// Copyright 2023 Stacklok, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// NOTE: This file is for stubbing out client code for proof of concept +// purposes. It will / should be removed in the future. +// Until then, it is not covered by unit tests and should not be used +// It does make a good example of how to use the generated client code +// for others to use as a reference. + +// Package useragent contains utilities for setting up the CLI's user agent +package useragent + +import ( + "fmt" + "runtime" + + "github.com/stacklok/minder/internal/constants" +) + +// GetUserAgent returns the user agent string for the CLI +// Note that the user agent used here replicates the user agent used by the +// browsers. +// e.g. / () () +// +// In our case, we'll leave extensions empty. +func GetUserAgent() string { + product := "minder-cli" + productVersion := constants.CLIVersion + + userAgent := fmt.Sprintf("%s/%s (%s) %s (%s)", + product, productVersion, runtime.GOOS, runtime.GOARCH, runtime.Version()) + + return userAgent +} diff --git a/internal/util/helpers.go b/internal/util/helpers.go index 6f71bdb303..ce88437e63 100644 --- a/internal/util/helpers.go +++ b/internal/util/helpers.go @@ -56,6 +56,7 @@ import ( "github.com/stacklok/minder/internal/constants" "github.com/stacklok/minder/internal/db" + "github.com/stacklok/minder/internal/util/cli/useragent" "github.com/stacklok/minder/internal/util/jsonyaml" minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1" ) @@ -152,11 +153,16 @@ func GrpcForCommand(cmd *cobra.Command, v *viper.Viper) (*grpc.ClientConn, error realm := GetConfigValue(v, "identity.cli.realm", "identity-realm", cmd, "stacklok").(string) clientId := GetConfigValue(v, "identity.cli.client_id", "identity-client", cmd, "minder-cli").(string) - return GetGrpcConnection(grpc_host, grpc_port, allowInsecure, issuerUrl, realm, clientId) + return GetGrpcConnection( + grpc_host, grpc_port, allowInsecure, issuerUrl, realm, clientId, grpc.WithUserAgent(useragent.GetUserAgent())) } // GetGrpcConnection is a helper for getting a testing connection for grpc -func GetGrpcConnection(grpc_host string, grpc_port int, allowInsecure bool, issuerUrl string, realm string, clientId string) ( +func GetGrpcConnection( + grpc_host string, grpc_port int, + allowInsecure bool, + issuerUrl string, realm string, clientId string, + opts ...grpc.DialOption) ( *grpc.ClientConn, error) { address := fmt.Sprintf("%s:%d", grpc_host, grpc_port) @@ -172,12 +178,14 @@ func GetGrpcConnection(grpc_host string, grpc_port int, allowInsecure bool, issu credentialOpts = insecure.NewCredentials() } - // generate credentials - conn, err := grpc.Dial( - address, grpc.WithTransportCredentials(credentialOpts), + dialOpts := []grpc.DialOption{ + grpc.WithTransportCredentials(credentialOpts), grpc.WithPerRPCCredentials(JWTTokenCredentials{accessToken: token}), - grpc.WithUserAgent(fmt.Sprintf("minder-cli/%s", constants.CLIVersion)), - ) + } + dialOpts = append(dialOpts, opts...) + + // generate credentials + conn, err := grpc.Dial(address, dialOpts...) if err != nil { return nil, fmt.Errorf("error connecting to gRPC server: %v", err) }