Skip to content

Commit 71bb798

Browse files
committed
[extensionauth] Split by protocol type
1 parent e0d365a commit 71bb798

19 files changed

+351
-121
lines changed

.chloggen/mx-psi_seal-them-all.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ issues: [12567]
1616
# These lines will be padded with 2 spaces and then inserted directly into the document.
1717
# Use pipe (|) for multiline entries.
1818
subtext: |
19-
Use the standard `extensionauth.NewClient` constructor to create a client with a specific mock implementation. Use `extensionauthtest.NewErrorClient` to create a client that always returns an error.
19+
- Use `extensionauthtest.NewNopClient` to create a client with a noop implementation.
20+
- Use `extensionauthtest.NewErrorClient` to create a client that always returns an error.
21+
- Implement the `extensionauth` interfaces for custom mock client implementations.
2022
2123
# Optional: The change log or logs in which this entry should be included.
2224
# e.g. '[user]' or '[user, api]'

config/configauth/configauth.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import (
1717

1818
var (
1919
errAuthenticatorNotFound = errors.New("authenticator not found")
20-
errNotClient = errors.New("requested authenticator is not a client authenticator")
20+
errNotHTTPClient = errors.New("requested authenticator is not a HTTP client authenticator")
21+
errNotGRPCClient = errors.New("requested authenticator is not a gRPC client authenticator")
2122
errNotServer = errors.New("requested authenticator is not a server authenticator")
2223
)
2324

@@ -40,15 +41,28 @@ func (a Authentication) GetServerAuthenticator(_ context.Context, extensions map
4041
return nil, fmt.Errorf("failed to resolve authenticator %q: %w", a.AuthenticatorID, errAuthenticatorNotFound)
4142
}
4243

43-
// GetClientAuthenticator attempts to select the appropriate extensionauth.Client from the list of extensions,
44+
// GetHTTPClientAuthenticator attempts to select the appropriate extensionauth.Client from the list of extensions,
4445
// based on the component id of the extension. If an authenticator is not found, an error is returned.
4546
// This should be only used by HTTP clients.
46-
func (a Authentication) GetClientAuthenticator(_ context.Context, extensions map[component.ID]component.Component) (extensionauth.Client, error) {
47+
func (a Authentication) GetHTTPClientAuthenticator(_ context.Context, extensions map[component.ID]component.Component) (extensionauth.HTTPClient, error) {
4748
if ext, found := extensions[a.AuthenticatorID]; found {
48-
if client, ok := ext.(extensionauth.Client); ok {
49+
if client, ok := ext.(extensionauth.HTTPClient); ok {
4950
return client, nil
5051
}
51-
return nil, errNotClient
52+
return nil, errNotHTTPClient
53+
}
54+
return nil, fmt.Errorf("failed to resolve authenticator %q: %w", a.AuthenticatorID, errAuthenticatorNotFound)
55+
}
56+
57+
// GetGRPCClientAuthenticator attempts to select the appropriate extensionauth.Client from the list of extensions,
58+
// based on the component id of the extension. If an authenticator is not found, an error is returned.
59+
// This should be only used by gRPC clients.
60+
func (a Authentication) GetGRPCClientAuthenticator(_ context.Context, extensions map[component.ID]component.Component) (extensionauth.GRPCClient, error) {
61+
if ext, found := extensions[a.AuthenticatorID]; found {
62+
if client, ok := ext.(extensionauth.GRPCClient); ok {
63+
return client, nil
64+
}
65+
return nil, errNotGRPCClient
5266
}
5367
return nil, fmt.Errorf("failed to resolve authenticator %q: %w", a.AuthenticatorID, errAuthenticatorNotFound)
5468
}

config/configauth/configauth_test.go

+15-30
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,26 @@ import (
1212

1313
"go.opentelemetry.io/collector/component"
1414
"go.opentelemetry.io/collector/extension"
15-
"go.opentelemetry.io/collector/extension/extensionauth"
15+
"go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest"
1616
)
1717

1818
var mockID = component.MustNewID("mock")
1919

20-
func must[T any](t *testing.T, builder func() (T, error)) T {
21-
t.Helper()
22-
thing, err := builder()
23-
require.NoError(t, err)
24-
return thing
25-
}
26-
2720
func TestGetServer(t *testing.T) {
2821
testCases := []struct {
2922
name string
3023
authenticator extension.Extension
3124
expected error
3225
}{
3326
{
34-
name: "obtain server authenticator",
35-
authenticator: must(t, func() (extension.Extension, error) {
36-
return extensionauth.NewServer()
37-
}),
38-
expected: nil,
27+
name: "obtain server authenticator",
28+
authenticator: extensionauthtest.NewNopServer(),
29+
expected: nil,
3930
},
4031
{
41-
name: "not a server authenticator",
42-
authenticator: must(t, func() (extension.Extension, error) {
43-
return extensionauth.NewClient()
44-
}),
45-
expected: errNotServer,
32+
name: "not a server authenticator",
33+
authenticator: extensionauthtest.NewNopClient(),
34+
expected: errNotServer,
4635
},
4736
}
4837
for _, tt := range testCases {
@@ -86,18 +75,14 @@ func TestGetClient(t *testing.T) {
8675
expected error
8776
}{
8877
{
89-
name: "obtain client authenticator",
90-
authenticator: must(t, func() (extension.Extension, error) {
91-
return extensionauth.NewClient()
92-
}),
93-
expected: nil,
78+
name: "obtain client authenticator",
79+
authenticator: extensionauthtest.NewNopClient(),
80+
expected: nil,
9481
},
9582
{
96-
name: "not a client authenticator",
97-
authenticator: must(t, func() (extension.Extension, error) {
98-
return extensionauth.NewServer()
99-
}),
100-
expected: errNotClient,
83+
name: "not a client authenticator",
84+
authenticator: extensionauthtest.NewNopServer(),
85+
expected: errNotHTTPClient,
10186
},
10287
}
10388
for _, tt := range testCases {
@@ -110,7 +95,7 @@ func TestGetClient(t *testing.T) {
11095
mockID: tt.authenticator,
11196
}
11297

113-
authenticator, err := cfg.GetClientAuthenticator(context.Background(), ext)
98+
authenticator, err := cfg.GetHTTPClientAuthenticator(context.Background(), ext)
11499

115100
// verify
116101
if tt.expected != nil {
@@ -128,7 +113,7 @@ func TestGetClientFails(t *testing.T) {
128113
cfg := &Authentication{
129114
AuthenticatorID: component.MustNewID("does_not_exist"),
130115
}
131-
authenticator, err := cfg.GetClientAuthenticator(context.Background(), map[component.ID]component.Component{})
116+
authenticator, err := cfg.GetGRPCClientAuthenticator(context.Background(), map[component.ID]component.Component{})
132117
require.ErrorIs(t, err, errAuthenticatorNotFound)
133118
assert.Nil(t, authenticator)
134119
}

config/configauth/go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
go.opentelemetry.io/collector/component v1.27.0
88
go.opentelemetry.io/collector/extension v1.27.0
99
go.opentelemetry.io/collector/extension/extensionauth v0.121.0
10+
go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.121.0
1011
go.uber.org/goleak v1.3.0
1112
)
1213

@@ -38,3 +39,5 @@ replace go.opentelemetry.io/collector/component/componenttest => ../../component
3839
replace go.opentelemetry.io/collector/extension => ../../extension
3940

4041
replace go.opentelemetry.io/collector/extension/extensionauth => ../../extension/extensionauth
42+
43+
replace go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest => ../../extension/extensionauth/extensionauthtest

config/configgrpc/configgrpc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ func (gcs *ClientConfig) getGrpcDialOptions(
322322
return nil, errors.New("no extensions configuration available")
323323
}
324324

325-
grpcAuthenticator, cerr := gcs.Auth.GetClientAuthenticator(ctx, host.GetExtensions())
325+
grpcAuthenticator, cerr := gcs.Auth.GetGRPCClientAuthenticator(ctx, host.GetExtensions())
326326
if cerr != nil {
327327
return nil, cerr
328328
}

config/configgrpc/configgrpc_test.go

+36-20
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,38 @@ import (
2929
"go.opentelemetry.io/collector/config/confignet"
3030
"go.opentelemetry.io/collector/config/configopaque"
3131
"go.opentelemetry.io/collector/config/configtls"
32+
"go.opentelemetry.io/collector/extension"
3233
"go.opentelemetry.io/collector/extension/extensionauth"
34+
"go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest"
3335
"go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp"
3436
)
3537

36-
func mustNewServerAuth(t *testing.T, opts ...extensionauth.ServerOption) extensionauth.Server {
37-
t.Helper()
38-
srv, err := extensionauth.NewServer(opts...)
39-
require.NoError(t, err)
40-
return srv
38+
var (
39+
_ extension.Extension = (*mockAuthServer)(nil)
40+
_ extensionauth.Server = (*mockAuthServer)(nil)
41+
)
42+
43+
type mockAuthServer struct {
44+
auth func(ctx context.Context, sources map[string][]string) (context.Context, error)
4145
}
4246

43-
func mustNewClientAuth(t *testing.T, opts ...extensionauth.ClientOption) extensionauth.Client {
44-
t.Helper()
45-
client, err := extensionauth.NewClient(opts...)
46-
require.NoError(t, err)
47-
return client
47+
// Authenticate implements extensionauth.Server.
48+
func (m *mockAuthServer) Authenticate(ctx context.Context, sources map[string][]string) (context.Context, error) {
49+
return m.auth(ctx, sources)
50+
}
51+
52+
// Shutdown implements extension.Extension.
53+
func (m *mockAuthServer) Shutdown(context.Context) error {
54+
return nil
55+
}
56+
57+
// Start implements extension.Extension.
58+
func (m *mockAuthServer) Start(context.Context, component.Host) error {
59+
return nil
60+
}
61+
62+
func newMockAuthServer(auth func(ctx context.Context, sources map[string][]string) (context.Context, error)) extensionauth.Server {
63+
return &mockAuthServer{auth: auth}
4864
}
4965

5066
func TestNewDefaultKeepaliveClientConfig(t *testing.T) {
@@ -177,7 +193,7 @@ func TestAllGrpcClientSettings(t *testing.T) {
177193
},
178194
host: &mockHost{
179195
ext: map[component.ID]component.Component{
180-
testAuthID: mustNewClientAuth(t),
196+
testAuthID: extensionauthtest.NewNopClient(),
181197
},
182198
},
183199
},
@@ -206,7 +222,7 @@ func TestAllGrpcClientSettings(t *testing.T) {
206222
},
207223
host: &mockHost{
208224
ext: map[component.ID]component.Component{
209-
testAuthID: mustNewClientAuth(t),
225+
testAuthID: extensionauthtest.NewNopClient(),
210226
},
211227
},
212228
},
@@ -235,7 +251,7 @@ func TestAllGrpcClientSettings(t *testing.T) {
235251
},
236252
host: &mockHost{
237253
ext: map[component.ID]component.Component{
238-
testAuthID: mustNewClientAuth(t),
254+
testAuthID: extensionauthtest.NewNopClient(),
239255
},
240256
},
241257
},
@@ -415,7 +431,7 @@ func TestGrpcServerAuthSettings(t *testing.T) {
415431

416432
host := &mockHost{
417433
ext: map[component.ID]component.Component{
418-
mockID: mustNewServerAuth(t),
434+
mockID: extensionauthtest.NewNopServer(),
419435
},
420436
}
421437
srv, err := gss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings())
@@ -990,7 +1006,7 @@ func TestDefaultUnaryInterceptorAuthSucceeded(t *testing.T) {
9901006
ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "some-auth-data"))
9911007

9921008
// test
993-
res, err := authUnaryServerInterceptor(ctx, nil, &grpc.UnaryServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1009+
res, err := authUnaryServerInterceptor(ctx, nil, &grpc.UnaryServerInfo{}, handler, newMockAuthServer(authFunc))
9941010

9951011
// verify
9961012
assert.Nil(t, res)
@@ -1014,7 +1030,7 @@ func TestDefaultUnaryInterceptorAuthFailure(t *testing.T) {
10141030
ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorization", "some-auth-data"))
10151031

10161032
// test
1017-
res, err := authUnaryServerInterceptor(ctx, nil, &grpc.UnaryServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1033+
res, err := authUnaryServerInterceptor(ctx, nil, &grpc.UnaryServerInfo{}, handler, newMockAuthServer(authFunc))
10181034

10191035
// verify
10201036
assert.Nil(t, res)
@@ -1035,7 +1051,7 @@ func TestDefaultUnaryInterceptorMissingMetadata(t *testing.T) {
10351051
}
10361052

10371053
// test
1038-
res, err := authUnaryServerInterceptor(context.Background(), nil, &grpc.UnaryServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1054+
res, err := authUnaryServerInterceptor(context.Background(), nil, &grpc.UnaryServerInfo{}, handler, newMockAuthServer(authFunc))
10391055

10401056
// verify
10411057
assert.Nil(t, res)
@@ -1066,7 +1082,7 @@ func TestDefaultStreamInterceptorAuthSucceeded(t *testing.T) {
10661082
}
10671083

10681084
// test
1069-
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1085+
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, newMockAuthServer(authFunc))
10701086

10711087
// verify
10721088
require.NoError(t, err)
@@ -1092,7 +1108,7 @@ func TestDefaultStreamInterceptorAuthFailure(t *testing.T) {
10921108
}
10931109

10941110
// test
1095-
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1111+
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, newMockAuthServer(authFunc))
10961112

10971113
// verify
10981114
require.ErrorContains(t, err, expectedErr.Error()) // unfortunately, grpc errors don't wrap the original ones
@@ -1115,7 +1131,7 @@ func TestDefaultStreamInterceptorMissingMetadata(t *testing.T) {
11151131
}
11161132

11171133
// test
1118-
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, mustNewServerAuth(t, extensionauth.WithServerAuthenticate(authFunc)))
1134+
err := authStreamServerInterceptor(nil, streamServer, &grpc.StreamServerInfo{}, handler, newMockAuthServer(authFunc))
11191135

11201136
// verify
11211137
assert.Equal(t, errMetadataNotFound, err)

config/configgrpc/go.mod

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ require (
1313
go.opentelemetry.io/collector/config/confignet v1.27.0
1414
go.opentelemetry.io/collector/config/configopaque v1.27.0
1515
go.opentelemetry.io/collector/config/configtls v1.27.0
16+
go.opentelemetry.io/collector/extension v1.27.0
1617
go.opentelemetry.io/collector/extension/extensionauth v0.121.0
18+
go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.121.0
1719
go.opentelemetry.io/collector/pdata v1.27.0
1820
go.opentelemetry.io/collector/pdata/testdata v0.121.0
1921
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0
@@ -36,7 +38,6 @@ require (
3638
github.com/modern-go/reflect2 v1.0.2 // indirect
3739
github.com/pmezard/go-difflib v1.0.0 // indirect
3840
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
39-
go.opentelemetry.io/collector/extension v1.27.0 // indirect
4041
go.opentelemetry.io/collector/pdata/pprofile v0.121.0 // indirect
4142
go.opentelemetry.io/otel/metric v1.35.0 // indirect
4243
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
@@ -79,3 +80,5 @@ replace go.opentelemetry.io/collector/component => ../../component
7980
replace go.opentelemetry.io/collector/component/componenttest => ../../component/componenttest
8081

8182
replace go.opentelemetry.io/collector/consumer => ../../consumer
83+
84+
replace go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest => ../../extension/extensionauth/extensionauthtest

config/confighttp/confighttp.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func (hcs *ClientConfig) ToClient(ctx context.Context, host component.Host, sett
203203
return nil, errors.New("extensions configuration not found")
204204
}
205205

206-
httpCustomAuthRoundTripper, aerr := hcs.Auth.GetClientAuthenticator(ctx, ext)
206+
httpCustomAuthRoundTripper, aerr := hcs.Auth.GetHTTPClientAuthenticator(ctx, ext)
207207
if aerr != nil {
208208
return nil, aerr
209209
}

0 commit comments

Comments
 (0)