Skip to content

Commit 739648e

Browse files
authored
[extension/apikeyauth] Set user-agent (#901)
Set User-Agent based on collector instead of using go-elasticsearch default UA
1 parent 1e43a15 commit 739648e

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

extension/apikeyauthextension/authenticator.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ import (
2727
"fmt"
2828
"hash/fnv"
2929
"net/http"
30+
"runtime"
3031
"strings"
3132

3233
"go.opentelemetry.io/collector/client"
3334
"go.opentelemetry.io/collector/component"
35+
"go.opentelemetry.io/collector/extension"
3436
"go.opentelemetry.io/collector/extension/extensionauth"
3537
"golang.org/x/crypto/pbkdf2"
3638
"google.golang.org/genproto/googleapis/rpc/errdetails"
@@ -91,13 +93,14 @@ func (a *authData) GetAttributeNames() []string {
9193
type authenticator struct {
9294
config *Config
9395
telemetrySettings component.TelemetrySettings
96+
userAgent string
9497

9598
esClient *elasticsearch.TypedClient
9699
cache freelru.Cache[string, *cacheEntry]
97100
salt [16]byte // used for deriving keys from API Keys
98101
}
99102

100-
func newAuthenticator(cfg *Config, set component.TelemetrySettings) (*authenticator, error) {
103+
func newAuthenticator(cfg *Config, set extension.Settings) (*authenticator, error) {
101104
cache, err := freelru.NewSharded[string, *cacheEntry](cfg.Cache.Capacity, func(key string) uint32 {
102105
h := fnv.New32a()
103106
h.Write([]byte(key))
@@ -108,9 +111,18 @@ func newAuthenticator(cfg *Config, set component.TelemetrySettings) (*authentica
108111
}
109112
cache.SetLifetime(cfg.Cache.TTL)
110113

114+
userAgent := fmt.Sprintf(
115+
"%s/%s (%s/%s)",
116+
set.BuildInfo.Description,
117+
set.BuildInfo.Version,
118+
runtime.GOOS,
119+
runtime.GOARCH,
120+
)
121+
111122
authenticator := &authenticator{
112123
config: cfg,
113-
telemetrySettings: set,
124+
telemetrySettings: set.TelemetrySettings,
125+
userAgent: userAgent,
114126
cache: cache,
115127
}
116128
if _, err := rand.Read(authenticator.salt[:]); err != nil {
@@ -126,6 +138,9 @@ func (a *authenticator) Start(ctx context.Context, host component.Host) error {
126138
}
127139
esClient, err := elasticsearch.NewTypedClient(elasticsearch.Config{
128140
Addresses: []string{a.config.Endpoint},
141+
Header: map[string][]string{
142+
"User-Agent": {a.userAgent},
143+
},
129144
Transport: httpClient.Transport,
130145
Instrumentation: elasticsearch.NewOpenTelemetryInstrumentation(
131146
a.telemetrySettings.TracerProvider, false,

extension/apikeyauthextension/authenticator_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"fmt"
2525
"net/http"
2626
"net/http/httptest"
27+
"strings"
2728
"testing"
2829
"time"
2930

@@ -33,9 +34,12 @@ import (
3334
"github.com/stretchr/testify/require"
3435
"go.opentelemetry.io/collector/client"
3536
"go.opentelemetry.io/collector/component/componenttest"
37+
"go.opentelemetry.io/collector/extension/extensiontest"
3638
"google.golang.org/genproto/googleapis/rpc/errdetails"
3739
"google.golang.org/grpc/codes"
3840
"google.golang.org/grpc/status"
41+
42+
"github.com/elastic/opentelemetry-collector-components/extension/apikeyauthextension/internal/metadata"
3943
)
4044

4145
const user = "test"
@@ -196,6 +200,21 @@ func TestAuthenticator_Caching(t *testing.T) {
196200
assert.EqualError(t, err, `rpc error: code = Unauthenticated desc = API Key "id2" unauthorized`)
197201
}
198202

203+
func TestAuthenticator_UserAgent(t *testing.T) {
204+
srv := newMockElasticsearch(t, func(w http.ResponseWriter, r *http.Request) {
205+
wantPrefix := "OpenTelemetry Collector/latest ("
206+
userAgent := r.Header.Get("User-Agent")
207+
assert.Truef(t, strings.HasPrefix(userAgent, wantPrefix), "want prefix %s; got %s", wantPrefix, userAgent)
208+
assert.NoError(t, json.NewEncoder(w).Encode(successfulResponse))
209+
})
210+
211+
authenticator := newTestAuthenticator(t, srv, createDefaultConfig().(*Config))
212+
_, err := authenticator.Authenticate(context.Background(), map[string][]string{
213+
"Authorization": {"ApiKey " + base64.StdEncoding.EncodeToString([]byte("id:secret"))},
214+
})
215+
assert.NoError(t, err)
216+
}
217+
199218
func TestAuthenticator_ErrorWithDetails(t *testing.T) {
200219
for name, testcase := range map[string]struct {
201220
setup func(*testing.T) (*authenticator, map[string][]string)
@@ -483,7 +502,7 @@ func BenchmarkAuthenticator(b *testing.B) {
483502

484503
func newTestAuthenticator(t testing.TB, srv *httptest.Server, config *Config) *authenticator {
485504
config.Endpoint = srv.URL
486-
auth, err := newAuthenticator(config, componenttest.NewNopTelemetrySettings())
505+
auth, err := newAuthenticator(config, extensiontest.NewNopSettings(metadata.Type))
487506
require.NoError(t, err)
488507

489508
err = auth.Start(context.Background(), componenttest.NewNopHost())

extension/apikeyauthextension/factory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,5 @@ func NewFactory() extension.Factory {
3636
}
3737

3838
func createExtension(_ context.Context, set extension.Settings, cfg component.Config) (extension.Extension, error) {
39-
return newAuthenticator(cfg.(*Config), set.TelemetrySettings)
39+
return newAuthenticator(cfg.(*Config), set)
4040
}

0 commit comments

Comments
 (0)