Skip to content

Commit c3c16db

Browse files
committed
[confighttp] Add option to include query params in auth context
This PR adds a new option to the ServerConfig's Auth option, allowing users to specify a list of query parameters to add to the sources of auth data, in addition to HTTP headers. Instead of simply adding all parameters, which might be numeruous, we require users to specify which ones to include. Auth extensions don't need to be changed, but should document which attributes they expect to find in the context and how to configure confighttp to accomplish that. Fixes open-telemetry#4806 Signed-off-by: Juraci Paixão Kröhling <[email protected]>
1 parent 05a2844 commit c3c16db

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

config/confighttp/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ will not be enabled.
7878
- `compression_algorithms`: configures the list of compression algorithms the server can accept. Default: ["", "gzip", "zstd", "zlib", "snappy", "deflate"]
7979
- [`tls`](../configtls/README.md)
8080
- [`auth`](../configauth/README.md)
81+
- `request_params`: a list of query parameter names to add to the auth context, along with the HTTP headers
8182

8283
You can enable [`attribute processor`][attribute-processor] to append any http header to span's attribute using custom key. You also need to enable the "include_metadata"
8384

@@ -90,6 +91,8 @@ receivers:
9091
http:
9192
include_metadata: true
9293
auth:
94+
request_params:
95+
- token
9396
authenticator: some-authenticator-extension
9497
cors:
9598
allowed_origins:

config/confighttp/confighttp.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ type ServerConfig struct {
272272
CORS *CORSConfig `mapstructure:"cors"`
273273

274274
// Auth for this receiver
275-
Auth *configauth.Authentication `mapstructure:"auth"`
275+
Auth *AuthConfig `mapstructure:"auth"`
276276

277277
// MaxRequestBodySize sets the maximum request body size in bytes. Default: 20MiB.
278278
MaxRequestBodySize int64 `mapstructure:"max_request_body_size"`
@@ -289,6 +289,14 @@ type ServerConfig struct {
289289
CompressionAlgorithms []string `mapstructure:"compression_algorithms"`
290290
}
291291

292+
type AuthConfig struct {
293+
// Auth for this receiver.
294+
*configauth.Authentication `mapstructure:"-"`
295+
296+
// RequestParameters is a list of parameters that should be extracted from the request and added to the context.
297+
RequestParameters []string `mapstructure:"request_params"`
298+
}
299+
292300
// ToListener creates a net.Listener.
293301
func (hss *ServerConfig) ToListener(ctx context.Context) (net.Listener, error) {
294302
listener, err := net.Listen("tcp", hss.Endpoint)
@@ -368,7 +376,7 @@ func (hss *ServerConfig) ToServer(_ context.Context, host component.Host, settin
368376
return nil, err
369377
}
370378

371-
handler = authInterceptor(handler, server)
379+
handler = authInterceptor(handler, server, hss.Auth.RequestParameters)
372380
}
373381

374382
if hss.CORS != nil && len(hss.CORS.AllowedOrigins) > 0 {
@@ -448,9 +456,16 @@ type CORSConfig struct {
448456
MaxAge int `mapstructure:"max_age"`
449457
}
450458

451-
func authInterceptor(next http.Handler, server auth.Server) http.Handler {
459+
func authInterceptor(next http.Handler, server auth.Server, requestParams []string) http.Handler {
452460
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
453-
ctx, err := server.Authenticate(r.Context(), r.Header)
461+
sources := r.Header
462+
query := r.URL.Query()
463+
for _, param := range requestParams {
464+
if val, ok := query[param]; ok {
465+
sources[param] = val
466+
}
467+
}
468+
ctx, err := server.Authenticate(r.Context(), sources)
454469
if err != nil {
455470
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
456471
return

config/confighttp/confighttp_test.go

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -855,8 +855,10 @@ func TestHttpCorsWithSettings(t *testing.T) {
855855
CORS: &CORSConfig{
856856
AllowedOrigins: []string{"*"},
857857
},
858-
Auth: &configauth.Authentication{
859-
AuthenticatorID: mockID,
858+
Auth: &AuthConfig{
859+
Authentication: &configauth.Authentication{
860+
AuthenticatorID: mockID,
861+
},
860862
},
861863
}
862864

@@ -1158,8 +1160,10 @@ func TestServerAuth(t *testing.T) {
11581160
authCalled := false
11591161
hss := ServerConfig{
11601162
Endpoint: "localhost:0",
1161-
Auth: &configauth.Authentication{
1162-
AuthenticatorID: mockID,
1163+
Auth: &AuthConfig{
1164+
Authentication: &configauth.Authentication{
1165+
AuthenticatorID: mockID,
1166+
},
11631167
},
11641168
}
11651169

@@ -1192,8 +1196,10 @@ func TestServerAuth(t *testing.T) {
11921196

11931197
func TestInvalidServerAuth(t *testing.T) {
11941198
hss := ServerConfig{
1195-
Auth: &configauth.Authentication{
1196-
AuthenticatorID: nonExistingID,
1199+
Auth: &AuthConfig{
1200+
Authentication: &configauth.Authentication{
1201+
AuthenticatorID: nonExistingID,
1202+
},
11971203
},
11981204
}
11991205

@@ -1206,8 +1212,10 @@ func TestFailedServerAuth(t *testing.T) {
12061212
// prepare
12071213
hss := ServerConfig{
12081214
Endpoint: "localhost:0",
1209-
Auth: &configauth.Authentication{
1210-
AuthenticatorID: mockID,
1215+
Auth: &AuthConfig{
1216+
Authentication: &configauth.Authentication{
1217+
AuthenticatorID: mockID,
1218+
},
12111219
},
12121220
}
12131221
host := &mockHost{
@@ -1380,6 +1388,48 @@ func TestDefaultMaxRequestBodySize(t *testing.T) {
13801388
}
13811389
}
13821390

1391+
func TestAuthWithQueryParams(t *testing.T) {
1392+
// prepare
1393+
authCalled := false
1394+
hss := ServerConfig{
1395+
Endpoint: "localhost:0",
1396+
Auth: &AuthConfig{
1397+
RequestParameters: []string{"auth"},
1398+
Authentication: &configauth.Authentication{
1399+
AuthenticatorID: mockID,
1400+
},
1401+
},
1402+
}
1403+
1404+
host := &mockHost{
1405+
ext: map[component.ID]component.Component{
1406+
mockID: auth.NewServer(
1407+
auth.WithServerAuthenticate(func(ctx context.Context, sources map[string][]string) (context.Context, error) {
1408+
require.Len(t, sources, 1)
1409+
assert.Equal(t, "1", sources["auth"][0])
1410+
authCalled = true
1411+
return ctx, nil
1412+
}),
1413+
),
1414+
},
1415+
}
1416+
1417+
handlerCalled := false
1418+
handler := http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
1419+
handlerCalled = true
1420+
})
1421+
1422+
srv, err := hss.ToServer(context.Background(), host, componenttest.NewNopTelemetrySettings(), handler)
1423+
require.NoError(t, err)
1424+
1425+
// test
1426+
srv.Handler.ServeHTTP(&httptest.ResponseRecorder{}, httptest.NewRequest("GET", "/?auth=1", nil))
1427+
1428+
// verify
1429+
assert.True(t, handlerCalled)
1430+
assert.True(t, authCalled)
1431+
}
1432+
13831433
type mockHost struct {
13841434
component.Host
13851435
ext map[component.ID]component.Component

0 commit comments

Comments
 (0)