Skip to content

Commit f66845f

Browse files
authored
[bearertokenauthextension] Implement configauth ServerAuthenticator (open-telemetry#22739)
Closes open-telemetry#22737 --------- Signed-off-by: Benedikt Bongartz <[email protected]>
1 parent 6a83a9a commit f66845f

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
5+
component: bearertokenauthextension
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Extension now implements configauth.ServerAuthenticator
9+
10+
# One or more tracking issues related to the change
11+
issues: [22737]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

extension/bearertokenauthextension/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414

1515

16-
This extension implements `configauth.ClientAuthenticator` and can be used in both http and gRPC exporters inside the `auth` settings, as a means to embed a static token for every RPC call that will be made.
16+
This extension implements both `configauth.ServerAuthenticator` and `configauth.ClientAuthenticator`. It can be used in both http and gRPC exporters inside the `auth` settings, as a means to embed a static token for every RPC call that will be made.
1717

1818
The authenticator type has to be set to `bearertokenauth`.
1919

extension/bearertokenauthextension/bearertokenauth.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package bearertokenauthextension // import "github.com/open-telemetry/openteleme
55

66
import (
77
"context"
8+
"errors"
89
"fmt"
910
"net/http"
1011
"os"
@@ -34,6 +35,11 @@ func (c *PerRPCAuth) RequireTransportSecurity() bool {
3435
return true
3536
}
3637

38+
var (
39+
_ auth.Server = (*BearerTokenAuth)(nil)
40+
_ auth.Client = (*BearerTokenAuth)(nil)
41+
)
42+
3743
// BearerTokenAuth is an implementation of auth.Client. It embeds a static authorization "bearer" token in every rpc call.
3844
type BearerTokenAuth struct {
3945
muTokenString sync.RWMutex
@@ -171,6 +177,23 @@ func (b *BearerTokenAuth) RoundTripper(base http.RoundTripper) (http.RoundTrippe
171177
}, nil
172178
}
173179

180+
// Authenticate checks whether the given context contains valid auth data.
181+
func (b *BearerTokenAuth) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) {
182+
auth, ok := headers["authorization"]
183+
if !ok || len(auth) == 0 {
184+
return ctx, errors.New("authentication didn't succeed")
185+
}
186+
token := auth[0]
187+
expect := b.tokenString
188+
if len(b.scheme) != 0 {
189+
expect = fmt.Sprintf("%s %s", b.scheme, expect)
190+
}
191+
if expect != token {
192+
return ctx, fmt.Errorf("scheme or token does not match: %s", token)
193+
}
194+
return ctx, nil
195+
}
196+
174197
// BearerAuthRoundTripper intercepts and adds Bearer token Authorization headers to each http request.
175198
type BearerAuthRoundTripper struct {
176199
baseTransport http.RoundTripper

extension/bearertokenauthextension/bearertokenauth_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,54 @@ func TestBearerTokenFileContentUpdate(t *testing.T) {
200200
authHeaderValue = resp.Header.Get("Authorization")
201201
assert.Equal(t, authHeaderValue, fmt.Sprintf("%s %s", scheme, string(token)))
202202
}
203+
204+
func TestBearerServerAuthenticateWithScheme(t *testing.T) {
205+
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." // #nosec
206+
cfg := createDefaultConfig().(*Config)
207+
cfg.Scheme = "Bearer"
208+
cfg.BearerToken = token
209+
210+
bauth := newBearerTokenAuth(cfg, nil)
211+
assert.NotNil(t, bauth)
212+
213+
ctx := context.Background()
214+
assert.Nil(t, bauth.Start(ctx, componenttest.NewNopHost()))
215+
216+
_, err := bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + token}})
217+
assert.NoError(t, err)
218+
219+
_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + "1234"}})
220+
assert.Error(t, err)
221+
222+
_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"" + token}})
223+
assert.Error(t, err)
224+
225+
assert.Nil(t, bauth.Shutdown(context.Background()))
226+
}
227+
228+
func TestBearerServerAuthenticate(t *testing.T) {
229+
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." // #nosec
230+
cfg := createDefaultConfig().(*Config)
231+
cfg.Scheme = ""
232+
cfg.BearerToken = token
233+
234+
bauth := newBearerTokenAuth(cfg, nil)
235+
assert.NotNil(t, bauth)
236+
237+
ctx := context.Background()
238+
assert.Nil(t, bauth.Start(ctx, componenttest.NewNopHost()))
239+
240+
_, err := bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + token}})
241+
assert.Error(t, err)
242+
243+
_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + "1234"}})
244+
assert.Error(t, err)
245+
246+
_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"invalidtoken"}})
247+
assert.Error(t, err)
248+
249+
_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {token}})
250+
assert.NoError(t, err)
251+
252+
assert.Nil(t, bauth.Shutdown(context.Background()))
253+
}

0 commit comments

Comments
 (0)