Skip to content

Commit

Permalink
[bearertokenauthextension] Implement configauth ServerAuthenticator (o…
Browse files Browse the repository at this point in the history
…pen-telemetry#22739)

Closes open-telemetry#22737

---------

Signed-off-by: Benedikt Bongartz <bongartz@klimlive.de>
  • Loading branch information
frzifus authored and fchikwekwe committed Jun 23, 2023
1 parent cb0ff73 commit 5a47595
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
16 changes: 16 additions & 0 deletions .chloggen/bearertokenauthextension_impl_server_authenticator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: bearertokenauthextension

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Extension now implements configauth.ServerAuthenticator

# One or more tracking issues related to the change
issues: [22737]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
2 changes: 1 addition & 1 deletion extension/bearertokenauthextension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@



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.
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.

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

Expand Down
23 changes: 23 additions & 0 deletions extension/bearertokenauthextension/bearertokenauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package bearertokenauthextension // import "github.com/open-telemetry/openteleme

import (
"context"
"errors"
"fmt"
"net/http"
"os"
Expand Down Expand Up @@ -34,6 +35,11 @@ func (c *PerRPCAuth) RequireTransportSecurity() bool {
return true
}

var (
_ auth.Server = (*BearerTokenAuth)(nil)
_ auth.Client = (*BearerTokenAuth)(nil)
)

// BearerTokenAuth is an implementation of auth.Client. It embeds a static authorization "bearer" token in every rpc call.
type BearerTokenAuth struct {
muTokenString sync.RWMutex
Expand Down Expand Up @@ -171,6 +177,23 @@ func (b *BearerTokenAuth) RoundTripper(base http.RoundTripper) (http.RoundTrippe
}, nil
}

// Authenticate checks whether the given context contains valid auth data.
func (b *BearerTokenAuth) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) {
auth, ok := headers["authorization"]
if !ok || len(auth) == 0 {
return ctx, errors.New("authentication didn't succeed")
}
token := auth[0]
expect := b.tokenString
if len(b.scheme) != 0 {
expect = fmt.Sprintf("%s %s", b.scheme, expect)
}
if expect != token {
return ctx, fmt.Errorf("scheme or token does not match: %s", token)
}
return ctx, nil
}

// BearerAuthRoundTripper intercepts and adds Bearer token Authorization headers to each http request.
type BearerAuthRoundTripper struct {
baseTransport http.RoundTripper
Expand Down
51 changes: 51 additions & 0 deletions extension/bearertokenauthextension/bearertokenauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,54 @@ func TestBearerTokenFileContentUpdate(t *testing.T) {
authHeaderValue = resp.Header.Get("Authorization")
assert.Equal(t, authHeaderValue, fmt.Sprintf("%s %s", scheme, string(token)))
}

func TestBearerServerAuthenticateWithScheme(t *testing.T) {
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." // #nosec
cfg := createDefaultConfig().(*Config)
cfg.Scheme = "Bearer"
cfg.BearerToken = token

bauth := newBearerTokenAuth(cfg, nil)
assert.NotNil(t, bauth)

ctx := context.Background()
assert.Nil(t, bauth.Start(ctx, componenttest.NewNopHost()))

_, err := bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + token}})
assert.NoError(t, err)

_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + "1234"}})
assert.Error(t, err)

_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"" + token}})
assert.Error(t, err)

assert.Nil(t, bauth.Shutdown(context.Background()))
}

func TestBearerServerAuthenticate(t *testing.T) {
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." // #nosec
cfg := createDefaultConfig().(*Config)
cfg.Scheme = ""
cfg.BearerToken = token

bauth := newBearerTokenAuth(cfg, nil)
assert.NotNil(t, bauth)

ctx := context.Background()
assert.Nil(t, bauth.Start(ctx, componenttest.NewNopHost()))

_, err := bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + token}})
assert.Error(t, err)

_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"Bearer " + "1234"}})
assert.Error(t, err)

_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {"invalidtoken"}})
assert.Error(t, err)

_, err = bauth.Authenticate(ctx, map[string][]string{"authorization": {token}})
assert.NoError(t, err)

assert.Nil(t, bauth.Shutdown(context.Background()))
}

0 comments on commit 5a47595

Please sign in to comment.