Skip to content

Commit 1ff2f3f

Browse files
authored
[bearertokenauthextension] Load token lazily for gRPC AUTH to fix token refresh issue (open-telemetry#36749)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description For the gRPC client AUTH part of bearertokenauthextension, there's a token refresh issue which causes all telemetry rejected by server after a period of time. The old token is always used even if the token is refreshed in filesystem. The root cause is the token value is cached during the `PerRPCCredentials()` instead of retrieving the latest. This PR aims to fix it by loading the token lazily in `GetRequestMetadata()`. <!-- Issue number (e.g. open-telemetry#1234) or full URL to issue, if applicable. --> #### Link to tracking issue N/A. <!--Describe what testing was performed and which tests were added.--> #### Testing After I built a new docker image with this fix and tested in my environment, the token refresh issue didn't happen again after the first token expired. <!--Describe the documentation added.--> #### Documentation N/A. <!--Please delete paragraphs that you did not use before submitting.-->
1 parent 6d87048 commit 1ff2f3f

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: bug_fix
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: bearertokenauthextension
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Load token lazily for gRPC AUTH to fix token refresh issue
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [36749]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

extension/bearertokenauthextension/bearertokenauth.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ var _ credentials.PerRPCCredentials = (*PerRPCAuth)(nil)
2323

2424
// PerRPCAuth is a gRPC credentials.PerRPCCredentials implementation that returns an 'authorization' header.
2525
type PerRPCAuth struct {
26-
metadata map[string]string
26+
auth *BearerTokenAuth
2727
}
2828

2929
// GetRequestMetadata returns the request metadata to be used with the RPC.
3030
func (c *PerRPCAuth) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
31-
return c.metadata, nil
31+
return map[string]string{"authorization": c.auth.authorizationValue()}, nil
3232
}
3333

3434
// RequireTransportSecurity always returns true for this implementation. Passing bearer tokens in plain-text connections is a bad idea.
@@ -171,7 +171,7 @@ func (b *BearerTokenAuth) Shutdown(_ context.Context) error {
171171
// PerRPCCredentials returns PerRPCAuth an implementation of credentials.PerRPCCredentials that
172172
func (b *BearerTokenAuth) PerRPCCredentials() (credentials.PerRPCCredentials, error) {
173173
return &PerRPCAuth{
174-
metadata: map[string]string{"authorization": b.authorizationValue()},
174+
auth: b,
175175
}, nil
176176
}
177177

extension/bearertokenauthextension/bearertokenauth_test.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@ import (
1818
)
1919

2020
func TestPerRPCAuth(t *testing.T) {
21-
metadata := map[string]string{
22-
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
23-
}
21+
cfg := createDefaultConfig().(*Config)
22+
cfg.BearerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
2423

2524
// test meta data is properly
26-
perRPCAuth := &PerRPCAuth{metadata: metadata}
25+
bauth := newBearerTokenAuth(cfg, nil)
26+
assert.NotNil(t, bauth)
27+
perRPCAuth := &PerRPCAuth{auth: bauth}
2728
md, err := perRPCAuth.GetRequestMetadata(context.Background())
2829
assert.NoError(t, err)
29-
assert.Equal(t, md, metadata)
30+
expectedMetadata := map[string]string{
31+
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
32+
}
33+
assert.Equal(t, expectedMetadata, md)
3034

3135
// always true
3236
ok := perRPCAuth.RequireTransportSecurity()
@@ -202,6 +206,34 @@ func TestBearerTokenFileContentUpdate(t *testing.T) {
202206
assert.Equal(t, authHeaderValue, fmt.Sprintf("%s %s", scheme, string(token)))
203207
}
204208

209+
func TestBearerTokenUpdateForGrpc(t *testing.T) {
210+
// prepare
211+
cfg := createDefaultConfig().(*Config)
212+
cfg.BearerToken = "1234"
213+
214+
bauth := newBearerTokenAuth(cfg, zaptest.NewLogger(t))
215+
assert.NotNil(t, bauth)
216+
217+
perRPCAuth, err := bauth.PerRPCCredentials()
218+
assert.NoError(t, err)
219+
220+
ctx := context.Background()
221+
assert.NoError(t, bauth.Start(ctx, componenttest.NewNopHost()))
222+
223+
// initial token, OK
224+
md, err := perRPCAuth.GetRequestMetadata(context.Background())
225+
assert.NoError(t, err)
226+
assert.Equal(t, map[string]string{"authorization": "Bearer " + "1234"}, md)
227+
228+
// update the token
229+
bauth.setAuthorizationValue("5678")
230+
md, err = perRPCAuth.GetRequestMetadata(context.Background())
231+
assert.NoError(t, err)
232+
assert.Equal(t, map[string]string{"authorization": "Bearer " + "5678"}, md)
233+
234+
assert.NoError(t, bauth.Shutdown(context.Background()))
235+
}
236+
205237
func TestBearerServerAuthenticateWithScheme(t *testing.T) {
206238
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." // #nosec
207239
cfg := createDefaultConfig().(*Config)

0 commit comments

Comments
 (0)