From acbebd0e0123f42dc6411ff9bc4f81ae5d50cb00 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 25 Mar 2022 17:34:10 +0530 Subject: [PATCH 01/12] Add support for client basic auth --- extension/basicauthextension/extension.go | 82 +++++++++--- .../basicauthextension/extension_test.go | 118 ++++++++++++++++++ 2 files changed, 180 insertions(+), 20 deletions(-) diff --git a/extension/basicauthextension/extension.go b/extension/basicauthextension/extension.go index a23f0e6d0405..5da9876e781d 100644 --- a/extension/basicauthextension/extension.go +++ b/extension/basicauthextension/extension.go @@ -15,18 +15,19 @@ package basicauthextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension" import ( + "bytes" "context" "encoding/base64" "errors" "fmt" - "io" - "os" + "io/ioutil" + "net/http" "strings" "github.com/tg123/go-htpasswd" "go.opentelemetry.io/collector/client" "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/config/configauth" + creds "google.golang.org/grpc/credentials" ) var ( @@ -38,50 +39,54 @@ var ( ) type basicAuth struct { - htpasswd HtpasswdSettings - matchFunc func(username, password string) bool + htpasswd HtpasswdSettings + matchFunc func(username, password string) bool + userPassPair string } -func newExtension(cfg *Config) (configauth.ServerAuthenticator, error) { +func newExtension(cfg *Config) (*basicAuth, error) { if cfg.Htpasswd.File == "" && cfg.Htpasswd.Inline == "" { return nil, errNoCredentialSource } ba := basicAuth{ htpasswd: cfg.Htpasswd, } - return configauth.NewServerAuthenticator(configauth.WithStart(ba.start), configauth.WithAuthenticate(ba.authenticate)), nil + return &ba, nil } -func (ba *basicAuth) start(ctx context.Context, host component.Host) error { - var rs []io.Reader +func (ba *basicAuth) Start(ctx context.Context, host component.Host) error { + var buff bytes.Buffer if ba.htpasswd.File != "" { - f, err := os.Open(ba.htpasswd.File) + bytes, err := ioutil.ReadFile(ba.htpasswd.File) if err != nil { - return fmt.Errorf("open htpasswd file: %w", err) + return fmt.Errorf("open file error: %w", err) } - defer f.Close() - - rs = append(rs, f) - rs = append(rs, strings.NewReader("\n")) + buff.Write(bytes) + buff.WriteString("\n") } // Ensure that the inline content is read the last. // This way the inline content will override the content from file. - rs = append(rs, strings.NewReader(ba.htpasswd.Inline)) - mr := io.MultiReader(rs...) + if len(ba.htpasswd.Inline) > 0 { + buff.Truncate(buff.Len()) + buff.WriteString(ba.htpasswd.Inline) + } - htp, err := htpasswd.NewFromReader(mr, htpasswd.DefaultSystems, nil) + htp, err := htpasswd.NewFromReader(bytes.NewBuffer(buff.Bytes()), htpasswd.DefaultSystems, nil) if err != nil { return fmt.Errorf("read htpasswd content: %w", err) } - + ba.userPassPair = buff.String() ba.matchFunc = htp.Match + return nil +} +func (ba *basicAuth) Shutdown(ctx context.Context) error { return nil } -func (ba *basicAuth) authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { +func (ba *basicAuth) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { auth := getAuthHeader(headers) if auth == "" { return ctx, errNoAuth @@ -155,6 +160,17 @@ func parseBasicAuth(auth string) (*authData, error) { }, nil } +func getBasicAuth(auth string) (*authData, error) { + si := strings.Index(auth, ":") + if si < 0 { + return nil, errInvalidFormat + } + return &authData{ + username: auth[:si], + password: auth[si+1:], + }, nil +} + var _ client.AuthData = (*authData)(nil) type authData struct { @@ -177,3 +193,29 @@ func (a *authData) GetAttribute(name string) interface{} { func (*authData) GetAttributeNames() []string { return []string{"username", "raw"} } + +type basicAuthRoundTripper struct { + base http.RoundTripper + authData *authData +} + +func (b *basicAuthRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { + newRequest := request.Clone(request.Context()) + newRequest.SetBasicAuth(b.authData.username, b.authData.password) + return b.base.RoundTrip(newRequest) +} + +func (ba *basicAuth) RoundTripper(base http.RoundTripper) (http.RoundTripper, error) { + authData, err := getBasicAuth(ba.userPassPair) + if err != nil { + return nil, err + } + return &basicAuthRoundTripper{ + base: base, + authData: authData, + }, nil +} + +func (ba *basicAuth) PerRPCCredentials() (creds.PerRPCCredentials, error) { + return nil, nil +} diff --git a/extension/basicauthextension/extension_test.go b/extension/basicauthextension/extension_test.go index 689272226e26..b7f36270d46c 100644 --- a/extension/basicauthextension/extension_test.go +++ b/extension/basicauthextension/extension_test.go @@ -19,6 +19,7 @@ import ( "encoding/base64" "fmt" "io/ioutil" + "net/http" "os" "testing" @@ -127,6 +128,18 @@ func TestBasicAuth_InvalidPrefix(t *testing.T) { assert.Equal(t, errInvalidSchemePrefix, err) } +func TestBasicAuth_NoFile(t *testing.T) { + ext, err := newExtension(&Config{ + Htpasswd: HtpasswdSettings{ + File: "/non/existing/file", + }, + }) + require.NoError(t, err) + require.NotNil(t, ext) + + require.Error(t, ext.Start(context.Background(), componenttest.NewNopHost())) +} + func TestBasicAuth_InvalidFormat(t *testing.T) { ext, err := newExtension(&Config{ Htpasswd: HtpasswdSettings{ @@ -193,3 +206,108 @@ func TestBasicAuth_SupportedHeaders(t *testing.T) { assert.NoError(t, err) } } + +type mockRoundTripper struct{} + +func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + resp := &http.Response{StatusCode: http.StatusOK, Header: map[string][]string{}} + for k, v := range req.Header { + resp.Header[k] = v + } + return resp, nil +} + +func TestBasicAuth_ClientValid(t *testing.T) { + creds := "username:password" + ext, err := newExtension(&Config{ + Htpasswd: HtpasswdSettings{ + Inline: creds, + }, + }) + assert.NotNil(t, ext) + require.NoError(t, err) + + assert.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + + base := &mockRoundTripper{} + c, err := ext.RoundTripper(base) + assert.NoError(t, err) + assert.NotNil(t, c) + + authCreds := base64.StdEncoding.EncodeToString([]byte(creds)) + orgHeaders := http.Header{ + "Test-Header-1": []string{"test-value-1"}, + } + expectedHeaders := http.Header{ + "Test-Header-1": []string{"test-value-1"}, + "Authorization": {fmt.Sprintf("Basic %s", authCreds)}, + } + + resp, err := c.RoundTrip(&http.Request{Header: orgHeaders}) + assert.NoError(t, err) + assert.Equal(t, expectedHeaders, resp.Header) + assert.Nil(t, ext.Shutdown(context.Background())) +} + +func TestBasicAuth_ClientInValid(t *testing.T) { + creds := "invalid" + ext, err := newExtension(&Config{ + Htpasswd: HtpasswdSettings{ + Inline: creds, + }, + }) + assert.NotNil(t, ext) + require.NoError(t, err) + + assert.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + + base := &mockRoundTripper{} + _, err = ext.RoundTripper(base) + assert.Error(t, err) +} + +func Test_GetBasicAuth(t *testing.T) { + tests := []struct { + name string + auth string + want *authData + wantErr bool + }{ + { + name: "valid", + auth: "username:password", + want: &authData{ + username: "username", + password: "password", + }, + }, + { + name: "invalid", + auth: "invalid", + wantErr: true, + }, + { + name: "empty", + auth: "", + wantErr: true, + }, + { + name: "multiple colons", + auth: "username:password:extra", + want: &authData{ + username: "username", + password: "password:extra", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getBasicAuth(tt.auth) + if tt.wantErr { + require.Error(t, err) + return + } + require.Equal(t, tt.want, got) + }) + } +} From 644203cd683750b3fee6e144a6984821c0fbffb9 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 25 Mar 2022 17:49:44 +0530 Subject: [PATCH 02/12] Change Readme --- extension/basicauthextension/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/extension/basicauthextension/README.md b/extension/basicauthextension/README.md index 502268c19bba..02c31bc2b087 100644 --- a/extension/basicauthextension/README.md +++ b/extension/basicauthextension/README.md @@ -1,8 +1,8 @@ # Basic Authenticator -This extension implements `configauth.ServerAuthenticator` to authenticate clients using HTTP Basic Authentication. The authenticator type has to be set to `basicauth`. +This extension implements both `configauth.ServerAuthenticator` and `configauth.ClientAuthenticator` to authenticate clients and servers using HTTP Basic Authentication. The authenticator type has to be set to `basicauth`. -If authentication is successful `client.Info.Auth` will expose the following attributes: +When used as ServerAuthenticator, if the authentication is successful `client.Info.Auth` will expose the following attributes: - `username`: The username of the authenticated user. - `raw`: Raw base64 encoded credentials. @@ -27,8 +27,9 @@ receivers: processors: exporters: - logging: - logLevel: debug + otlphttp: + auth: + authenticator: basicauth service: extensions: [basicauth] @@ -36,7 +37,7 @@ service: traces: receivers: [otlp] processors: [] - exporters: [logging] + exporters: [otlphttp] ``` ### htpasswd From 4b2da9db7694cd8e15877e8bbdebe930a4564b1d Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 25 Mar 2022 17:55:37 +0530 Subject: [PATCH 03/12] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a00f1106a10..2a113361481f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### 💡 Enhancements 💡 - `k8seventsreceiver`: Add Api_version and resource_version (#8539) +- `basicauthextension`: Implement `configauth.ClientAuthenticator` so that the extension can also be used as HTTP client basic authenticator.(#8847) ### 🛑 Breaking changes 🛑 From 342552a2edb19ef4f2ca5812bb505451a3476269 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Thu, 31 Mar 2022 18:08:05 +0530 Subject: [PATCH 04/12] separate out client and server authenticator --- extension/basicauthextension/README.md | 34 +++-- extension/basicauthextension/config.go | 37 ++++- extension/basicauthextension/config_test.go | 78 ++++++++++ extension/basicauthextension/extension.go | 94 ++++++------ .../basicauthextension/extension_test.go | 135 +++++++----------- extension/basicauthextension/factory.go | 6 +- extension/basicauthextension/factory_test.go | 2 +- .../testdata/invalid_config_both.yml | 23 +++ .../testdata/invalid_config_none.yml | 18 +++ .../testdata/valid_config.yml | 26 ++++ 10 files changed, 316 insertions(+), 137 deletions(-) create mode 100644 extension/basicauthextension/config_test.go create mode 100644 extension/basicauthextension/testdata/invalid_config_both.yml create mode 100644 extension/basicauthextension/testdata/invalid_config_none.yml create mode 100644 extension/basicauthextension/testdata/valid_config.yml diff --git a/extension/basicauthextension/README.md b/extension/basicauthextension/README.md index 02c31bc2b087..b18e5a0eece7 100644 --- a/extension/basicauthextension/README.md +++ b/extension/basicauthextension/README.md @@ -7,42 +7,52 @@ When used as ServerAuthenticator, if the authentication is successful `client.In - `username`: The username of the authenticated user. - `raw`: Raw base64 encoded credentials. +The configuration should specify only one instance of `basicauth` extension for either client or server authentication. + +The following are the configuration options: + +- `htpasswd.file`: The path to the htpasswd file. +- `htpasswd.inline`: The htpasswd file inline content. +- `htpasswd.client_auth`: Single username password combination in the form of `username:password` for client authentication. + +To configure the extension as a server authenticator, either one of `htpasswd.file` or `htpasswd.inline` has to be set. If both are configured, `htpasswd.inline` credentials take precedence. + +To configure the extension as a client authenticator, `htpasswd.client_auth` has to be set. + +If both the options are configured, the extension will throw an error. ## Configuration ```yaml extensions: - basicauth: + basicauth/server: htpasswd: file: .htpasswd inline: | ${BASIC_AUTH_USERNAME}:${BASIC_AUTH_PASSWORD} + + basicauth/client: + htpasswd: + client_auth: username:password receivers: otlp: protocols: http: auth: - authenticator: basicauth + authenticator: basicauth/server processors: exporters: otlphttp: auth: - authenticator: basicauth + authenticator: basicauth/client service: - extensions: [basicauth] + extensions: [basicauth/server, basicauth/client] pipelines: traces: receivers: [otlp] processors: [] exporters: [otlphttp] -``` - -### htpasswd - -- `file`: The path to the htpasswd file. -- `inline`: The htpasswd file inline content. - -If both `file` and `inline` are configured, `inline` credentials take precedence. \ No newline at end of file +``` \ No newline at end of file diff --git a/extension/basicauthextension/config.go b/extension/basicauthextension/config.go index 6c8b2dc54e4e..bed12f40e25e 100644 --- a/extension/basicauthextension/config.go +++ b/extension/basicauthextension/config.go @@ -14,7 +14,16 @@ package basicauthextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension" -import "go.opentelemetry.io/collector/config" +import ( + "errors" + + "go.opentelemetry.io/collector/config" +) + +var ( + errNoCredentialSource = errors.New("no credential source provided") + errMultipleAuthenticator = errors.New("only one of `htpasswd` or `client_auth` can be specified") +) type HtpasswdSettings struct { // Path to the htpasswd file. @@ -23,9 +32,33 @@ type HtpasswdSettings struct { Inline string `mapstructure:"inline"` } +type ClientAuthSettings struct { + // Username holds the username to use for client authentication. + Username string `mapstructure:"username"` + // Password holds the password to use for client authentication. + Password string `mapstructure:"password"` +} type Config struct { config.ExtensionSettings `mapstructure:",squash"` // Htpasswd settings. - Htpasswd HtpasswdSettings `mapstructure:"htpasswd"` + Htpasswd *HtpasswdSettings `mapstructure:"htpasswd,omitempty"` + + // ClientAuth settings + ClientAuth *ClientAuthSettings `mapstructure:"client_auth,omitempty"` +} + +func (cfg *Config) Validate() error { + serverCondition := cfg.Htpasswd != nil + clientCondition := cfg.ClientAuth != nil + + if serverCondition && clientCondition { + return errMultipleAuthenticator + } + + if !serverCondition && !clientCondition { + return errNoCredentialSource + } + + return nil } diff --git a/extension/basicauthextension/config_test.go b/extension/basicauthextension/config_test.go new file mode 100644 index 000000000000..f0bc78dae833 --- /dev/null +++ b/extension/basicauthextension/config_test.go @@ -0,0 +1,78 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package basicauthextension + +import ( + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/service/servicetest" +) + +func TestLoadConfig(t *testing.T) { + factories, err := componenttest.NopFactories() + require.NoError(t, err) + + factory := NewFactory() + factories.Extensions[typeStr] = factory + cfg, err := servicetest.LoadConfigAndValidate(filepath.Join("testdata", "valid_config.yml"), factories) + + require.NoError(t, err) + require.NotNil(t, cfg) + + ext0 := cfg.Extensions[config.NewComponentIDWithName(typeStr, "server")] + assert.Equal(t, &Config{ + ExtensionSettings: config.NewExtensionSettings(config.NewComponentIDWithName(typeStr, "server")), + Htpasswd: &HtpasswdSettings{ + Inline: "username1:password1\nusername2:password2\n", + }, + }, ext0) + + ext1 := cfg.Extensions[config.NewComponentIDWithName(typeStr, "client")] + assert.Equal(t, + &Config{ + ExtensionSettings: config.NewExtensionSettings(config.NewComponentIDWithName(typeStr, "client")), + ClientAuth: &ClientAuthSettings{ + Username: "username", + Password: "password", + }, + }, + ext1) + + assert.Equal(t, 2, len(cfg.Service.Extensions)) + assert.Equal(t, config.NewComponentIDWithName(typeStr, "client"), cfg.Service.Extensions[0]) + assert.Equal(t, config.NewComponentIDWithName(typeStr, "server"), cfg.Service.Extensions[1]) +} + +func TestLoadConfigError(t *testing.T) { + factories, err := componenttest.NopFactories() + require.NoError(t, err) + + factory := NewFactory() + factories.Extensions[typeStr] = factory + t.Run("invalid config both present", func(t *testing.T) { + _, err = servicetest.LoadConfigAndValidate(filepath.Join("testdata", "invalid_config_both.yml"), factories) + assert.Error(t, err) + }) + t.Run("invalid config none present", func(t *testing.T) { + _, err = servicetest.LoadConfigAndValidate(filepath.Join("testdata", "invalid_config_none.yml"), factories) + assert.Error(t, err) + }) + +} diff --git a/extension/basicauthextension/extension.go b/extension/basicauthextension/extension.go index 5da9876e781d..1c6324860be5 100644 --- a/extension/basicauthextension/extension.go +++ b/extension/basicauthextension/extension.go @@ -15,23 +15,23 @@ package basicauthextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension" import ( - "bytes" "context" "encoding/base64" "errors" "fmt" - "io/ioutil" + "io" "net/http" + "os" "strings" "github.com/tg123/go-htpasswd" "go.opentelemetry.io/collector/client" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/configauth" creds "google.golang.org/grpc/credentials" ) var ( - errNoCredentialSource = errors.New("no credential source provided") errNoAuth = errors.New("no basic auth provided") errInvalidCredentials = errors.New("invalid credentials") errInvalidSchemePrefix = errors.New("invalid authorization scheme prefix") @@ -39,54 +39,80 @@ var ( ) type basicAuth struct { - htpasswd HtpasswdSettings - matchFunc func(username, password string) bool - userPassPair string + htpasswd *HtpasswdSettings + clientAuth *ClientAuthSettings + matchFunc func(username, password string) bool } -func newExtension(cfg *Config) (*basicAuth, error) { - if cfg.Htpasswd.File == "" && cfg.Htpasswd.Inline == "" { +func newClientAuthExtension(cfg *Config) (configauth.ClientAuthenticator, error) { + if cfg.ClientAuth == nil || cfg.ClientAuth.Username == "" { return nil, errNoCredentialSource } + + ba := basicAuth{ + clientAuth: cfg.ClientAuth, + } + return configauth.NewClientAuthenticator( + configauth.WithClientStart(ba.clientStart), + configauth.WithClientShutdown(ba.shutdown), + configauth.WithClientRoundTripper(ba.RoundTripper), + ), nil +} + +func newServerAuthExtension(cfg *Config) (configauth.ServerAuthenticator, error) { + + if cfg.Htpasswd == nil || (cfg.Htpasswd.File == "" && cfg.Htpasswd.Inline == "") { + return nil, errNoCredentialSource + } + ba := basicAuth{ htpasswd: cfg.Htpasswd, } - return &ba, nil + return configauth.NewServerAuthenticator( + configauth.WithStart(ba.serverStart), + configauth.WithShutdown(ba.shutdown), + configauth.WithAuthenticate(ba.authenticate), + ), nil +} + +func (ba *basicAuth) clientStart(_ context.Context, _ component.Host) error { + return nil } -func (ba *basicAuth) Start(ctx context.Context, host component.Host) error { - var buff bytes.Buffer +func (ba *basicAuth) serverStart(ctx context.Context, host component.Host) error { + var rs []io.Reader if ba.htpasswd.File != "" { - bytes, err := ioutil.ReadFile(ba.htpasswd.File) + f, err := os.Open(ba.htpasswd.File) if err != nil { - return fmt.Errorf("open file error: %w", err) + return fmt.Errorf("open htpasswd file: %w", err) } - buff.Write(bytes) - buff.WriteString("\n") + defer f.Close() + + rs = append(rs, f) + rs = append(rs, strings.NewReader("\n")) } // Ensure that the inline content is read the last. // This way the inline content will override the content from file. - if len(ba.htpasswd.Inline) > 0 { - buff.Truncate(buff.Len()) - buff.WriteString(ba.htpasswd.Inline) - } + rs = append(rs, strings.NewReader(ba.htpasswd.Inline)) + mr := io.MultiReader(rs...) - htp, err := htpasswd.NewFromReader(bytes.NewBuffer(buff.Bytes()), htpasswd.DefaultSystems, nil) + htp, err := htpasswd.NewFromReader(mr, htpasswd.DefaultSystems, nil) if err != nil { return fmt.Errorf("read htpasswd content: %w", err) } - ba.userPassPair = buff.String() + ba.matchFunc = htp.Match + return nil } -func (ba *basicAuth) Shutdown(ctx context.Context) error { +func (ba *basicAuth) shutdown(ctx context.Context) error { return nil } -func (ba *basicAuth) Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { +func (ba *basicAuth) authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { auth := getAuthHeader(headers) if auth == "" { return ctx, errNoAuth @@ -160,17 +186,6 @@ func parseBasicAuth(auth string) (*authData, error) { }, nil } -func getBasicAuth(auth string) (*authData, error) { - si := strings.Index(auth, ":") - if si < 0 { - return nil, errInvalidFormat - } - return &authData{ - username: auth[:si], - password: auth[si+1:], - }, nil -} - var _ client.AuthData = (*authData)(nil) type authData struct { @@ -196,23 +211,22 @@ func (*authData) GetAttributeNames() []string { type basicAuthRoundTripper struct { base http.RoundTripper - authData *authData + authData *ClientAuthSettings } func (b *basicAuthRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { newRequest := request.Clone(request.Context()) - newRequest.SetBasicAuth(b.authData.username, b.authData.password) + newRequest.SetBasicAuth(b.authData.Username, b.authData.Password) return b.base.RoundTrip(newRequest) } func (ba *basicAuth) RoundTripper(base http.RoundTripper) (http.RoundTripper, error) { - authData, err := getBasicAuth(ba.userPassPair) - if err != nil { - return nil, err + if strings.Contains(ba.clientAuth.Username, ":") { + return nil, errInvalidFormat } return &basicAuthRoundTripper{ base: base, - authData: authData, + authData: ba.clientAuth, }, nil } diff --git a/extension/basicauthextension/extension_test.go b/extension/basicauthextension/extension_test.go index b7f36270d46c..75680346598b 100644 --- a/extension/basicauthextension/extension_test.go +++ b/extension/basicauthextension/extension_test.go @@ -70,8 +70,8 @@ func TestBasicAuth_Valid(t *testing.T) { ctx := context.Background() - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ File: f.Name(), }, }) @@ -95,8 +95,8 @@ func TestBasicAuth_Valid(t *testing.T) { } func TestBasicAuth_InvalidCredentials(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, }) @@ -107,8 +107,8 @@ func TestBasicAuth_InvalidCredentials(t *testing.T) { } func TestBasicAuth_NoHeader(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, }) @@ -118,8 +118,8 @@ func TestBasicAuth_NoHeader(t *testing.T) { } func TestBasicAuth_InvalidPrefix(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, }) @@ -129,8 +129,8 @@ func TestBasicAuth_InvalidPrefix(t *testing.T) { } func TestBasicAuth_NoFile(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ File: "/non/existing/file", }, }) @@ -141,8 +141,8 @@ func TestBasicAuth_NoFile(t *testing.T) { } func TestBasicAuth_InvalidFormat(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, }) @@ -166,8 +166,8 @@ func TestBasicAuth_HtpasswdInlinePrecedence(t *testing.T) { f.WriteString("username:fromfile") - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ File: f.Name(), Inline: "username:frominline", }, @@ -187,8 +187,8 @@ func TestBasicAuth_HtpasswdInlinePrecedence(t *testing.T) { } func TestBasicAuth_SupportedHeaders(t *testing.T) { - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ + ext, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, }) @@ -207,6 +207,13 @@ func TestBasicAuth_SupportedHeaders(t *testing.T) { } } +func TestBasicAuth_ServerInvalid(t *testing.T) { + _, err := newServerAuthExtension(&Config{ + Htpasswd: &HtpasswdSettings{}, + }) + assert.Error(t, err) +} + type mockRoundTripper struct{} func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { @@ -218,23 +225,23 @@ func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) } func TestBasicAuth_ClientValid(t *testing.T) { - creds := "username:password" - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ - Inline: creds, + ext, err := newClientAuthExtension(&Config{ + ClientAuth: &ClientAuthSettings{ + Username: "username", + Password: "password", }, }) - assert.NotNil(t, ext) + require.NotNil(t, ext) require.NoError(t, err) - assert.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + require.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) base := &mockRoundTripper{} c, err := ext.RoundTripper(base) - assert.NoError(t, err) - assert.NotNil(t, c) + require.NoError(t, err) + require.NotNil(t, c) - authCreds := base64.StdEncoding.EncodeToString([]byte(creds)) + authCreds := base64.StdEncoding.EncodeToString([]byte("username:password")) orgHeaders := http.Header{ "Test-Header-1": []string{"test-value-1"}, } @@ -250,64 +257,30 @@ func TestBasicAuth_ClientValid(t *testing.T) { } func TestBasicAuth_ClientInValid(t *testing.T) { - creds := "invalid" - ext, err := newExtension(&Config{ - Htpasswd: HtpasswdSettings{ - Inline: creds, - }, + t.Run("no username", func(t *testing.T) { + _, err := newClientAuthExtension(&Config{ + ClientAuth: &ClientAuthSettings{ + Username: "", + }, + }) + assert.Error(t, err) }) - assert.NotNil(t, ext) - require.NoError(t, err) - - assert.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) - - base := &mockRoundTripper{} - _, err = ext.RoundTripper(base) - assert.Error(t, err) -} -func Test_GetBasicAuth(t *testing.T) { - tests := []struct { - name string - auth string - want *authData - wantErr bool - }{ - { - name: "valid", - auth: "username:password", - want: &authData{ - username: "username", - password: "password", + t.Run("invalid username format", func(t *testing.T) { + ext, err := newClientAuthExtension(&Config{ + ClientAuth: &ClientAuthSettings{ + Username: "user:name", + Password: "password", }, - }, - { - name: "invalid", - auth: "invalid", - wantErr: true, - }, - { - name: "empty", - auth: "", - wantErr: true, - }, - { - name: "multiple colons", - auth: "username:password:extra", - want: &authData{ - username: "username", - password: "password:extra", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := getBasicAuth(tt.auth) - if tt.wantErr { - require.Error(t, err) - return - } - require.Equal(t, tt.want, got) }) - } + require.NotNil(t, ext) + require.NoError(t, err) + + require.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + + base := &mockRoundTripper{} + _, err = ext.RoundTripper(base) + assert.Error(t, err) + }) + } diff --git a/extension/basicauthextension/factory.go b/extension/basicauthextension/factory.go index d1d94dcc1392..8fa93b6d9373 100644 --- a/extension/basicauthextension/factory.go +++ b/extension/basicauthextension/factory.go @@ -40,5 +40,9 @@ func createDefaultConfig() config.Extension { } func createExtension(_ context.Context, _ component.ExtensionCreateSettings, cfg config.Extension) (component.Extension, error) { - return newExtension(cfg.(*Config)) + // check if config is a server auth(Htpasswd should be set) + if cfg.(*Config).Htpasswd != nil { + return newServerAuthExtension(cfg.(*Config)) + } + return newClientAuthExtension(cfg.(*Config)) } diff --git a/extension/basicauthextension/factory_test.go b/extension/basicauthextension/factory_test.go index bcc5d037a862..733c9aaca625 100644 --- a/extension/basicauthextension/factory_test.go +++ b/extension/basicauthextension/factory_test.go @@ -44,7 +44,7 @@ func TestCreateExtension_DefaultConfig(t *testing.T) { func TestCreateExtension_ValidConfig(t *testing.T) { cfg := &Config{ ExtensionSettings: config.NewExtensionSettings(config.NewComponentID(typeStr)), - Htpasswd: HtpasswdSettings{ + Htpasswd: &HtpasswdSettings{ Inline: "username:password", }, } diff --git a/extension/basicauthextension/testdata/invalid_config_both.yml b/extension/basicauthextension/testdata/invalid_config_both.yml new file mode 100644 index 000000000000..877f830aee32 --- /dev/null +++ b/extension/basicauthextension/testdata/invalid_config_both.yml @@ -0,0 +1,23 @@ +extensions: + basicauth/both: + client_auth: + username: user + password: pass + htpasswd: + file: /etc/nginx/htpasswd + +# Data pipeline is required to load the config. +receivers: + nop: +processors: + nop: +exporters: + nop: + +service: + extensions: [basicauth/both] + pipelines: + traces: + receivers: [nop] + processors: [nop] + exporters: [nop] diff --git a/extension/basicauthextension/testdata/invalid_config_none.yml b/extension/basicauthextension/testdata/invalid_config_none.yml new file mode 100644 index 000000000000..f60cf0d03c1c --- /dev/null +++ b/extension/basicauthextension/testdata/invalid_config_none.yml @@ -0,0 +1,18 @@ +extensions: + basicauth/none: + +# Data pipeline is required to load the config. +receivers: + nop: +processors: + nop: +exporters: + nop: + +service: + extensions: [basicauth/none] + pipelines: + traces: + receivers: [nop] + processors: [nop] + exporters: [nop] diff --git a/extension/basicauthextension/testdata/valid_config.yml b/extension/basicauthextension/testdata/valid_config.yml new file mode 100644 index 000000000000..46ac085cf41b --- /dev/null +++ b/extension/basicauthextension/testdata/valid_config.yml @@ -0,0 +1,26 @@ +extensions: + basicauth/client: + client_auth: + username: username + password: password + basicauth/server: + htpasswd: + inline: | + username1:password1 + username2:password2 + +# Data pipeline is required to load the config. +receivers: + nop: +processors: + nop: +exporters: + nop: + +service: + extensions: [basicauth/client, basicauth/server] + pipelines: + traces: + receivers: [nop] + processors: [nop] + exporters: [nop] From 0a33c894ae17c2429771eaac404ef292a4032282 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Tue, 5 Apr 2022 11:12:19 +0530 Subject: [PATCH 05/12] Fix Readme documentation Co-authored-by: Stepan Rakitin --- extension/basicauthextension/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/basicauthextension/README.md b/extension/basicauthextension/README.md index b18e5a0eece7..b5791cee462c 100644 --- a/extension/basicauthextension/README.md +++ b/extension/basicauthextension/README.md @@ -13,11 +13,11 @@ The following are the configuration options: - `htpasswd.file`: The path to the htpasswd file. - `htpasswd.inline`: The htpasswd file inline content. -- `htpasswd.client_auth`: Single username password combination in the form of `username:password` for client authentication. +- `client_auth`: Single username password combination in the form of `username:password` for client authentication. To configure the extension as a server authenticator, either one of `htpasswd.file` or `htpasswd.inline` has to be set. If both are configured, `htpasswd.inline` credentials take precedence. -To configure the extension as a client authenticator, `htpasswd.client_auth` has to be set. +To configure the extension as a client authenticator, `client_auth` has to be set. If both the options are configured, the extension will throw an error. ## Configuration From bbc4c1dd69e85cb55580a78751c9dddea78f04c2 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Tue, 12 Apr 2022 20:42:20 +0530 Subject: [PATCH 06/12] Update Readme.md --- extension/basicauthextension/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extension/basicauthextension/README.md b/extension/basicauthextension/README.md index b5791cee462c..b6250ce7ee54 100644 --- a/extension/basicauthextension/README.md +++ b/extension/basicauthextension/README.md @@ -31,8 +31,7 @@ extensions: ${BASIC_AUTH_USERNAME}:${BASIC_AUTH_PASSWORD} basicauth/client: - htpasswd: - client_auth: username:password + client_auth: username:password receivers: otlp: @@ -55,4 +54,4 @@ service: receivers: [otlp] processors: [] exporters: [otlphttp] -``` \ No newline at end of file +``` From 2ae7118f2ba831053fe34ffa85830a1aa6e92af9 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Wed, 13 Apr 2022 11:44:11 +0530 Subject: [PATCH 07/12] modify internal components test file --- internal/components/extensions_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/components/extensions_test.go b/internal/components/extensions_test.go index 5cf211bea481..1c191e15a4a2 100644 --- a/internal/components/extensions_test.go +++ b/internal/components/extensions_test.go @@ -92,7 +92,7 @@ func TestDefaultExtensions(t *testing.T) { cfg := extFactories["basicauth"].CreateDefaultConfig().(*basicauthextension.Config) f := testutil.NewTemporaryFile(t) f.WriteString("username:password") - cfg.Htpasswd = basicauthextension.HtpasswdSettings{ + cfg.Htpasswd = &basicauthextension.HtpasswdSettings{ File: f.Name(), Inline: "username:password", } From 7ffcfc34584185b6e86834a0f3d73684dd7a24b3 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 15 Apr 2022 13:49:48 +0530 Subject: [PATCH 08/12] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juraci Paixão Kröhling --- extension/basicauthextension/extension_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/basicauthextension/extension_test.go b/extension/basicauthextension/extension_test.go index 75680346598b..29261ba72244 100644 --- a/extension/basicauthextension/extension_test.go +++ b/extension/basicauthextension/extension_test.go @@ -234,7 +234,7 @@ func TestBasicAuth_ClientValid(t *testing.T) { require.NotNil(t, ext) require.NoError(t, err) - require.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) base := &mockRoundTripper{} c, err := ext.RoundTripper(base) @@ -253,10 +253,10 @@ func TestBasicAuth_ClientValid(t *testing.T) { resp, err := c.RoundTrip(&http.Request{Header: orgHeaders}) assert.NoError(t, err) assert.Equal(t, expectedHeaders, resp.Header) - assert.Nil(t, ext.Shutdown(context.Background())) + assert.NoError(t, ext.Shutdown(context.Background())) } -func TestBasicAuth_ClientInValid(t *testing.T) { +func TestBasicAuth_ClientInvalid(t *testing.T) { t.Run("no username", func(t *testing.T) { _, err := newClientAuthExtension(&Config{ ClientAuth: &ClientAuthSettings{ From 2971a6e076367b8296589e77666b15ca84f72f6a Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 15 Apr 2022 13:50:25 +0530 Subject: [PATCH 09/12] add rpc support --- extension/basicauthextension/extension.go | 25 ++++++++++++++- .../basicauthextension/extension_test.go | 32 ++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/extension/basicauthextension/extension.go b/extension/basicauthextension/extension.go index 1c6324860be5..0b99cb705403 100644 --- a/extension/basicauthextension/extension.go +++ b/extension/basicauthextension/extension.go @@ -56,6 +56,7 @@ func newClientAuthExtension(cfg *Config) (configauth.ClientAuthenticator, error) configauth.WithClientStart(ba.clientStart), configauth.WithClientShutdown(ba.shutdown), configauth.WithClientRoundTripper(ba.RoundTripper), + configauth.WithPerRPCCredentials(ba.PerRPCCredentials), ), nil } @@ -209,6 +210,20 @@ func (*authData) GetAttributeNames() []string { return []string{"username", "raw"} } +type perRPCAuth struct { + metadata map[string]string +} + +// GetRequestMetadata returns the request metadata to be used with the RPC. +func (p *perRPCAuth) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { + return p.metadata, nil +} + +// RequireTransportSecurity always returns true for this implementation. +func (p *perRPCAuth) RequireTransportSecurity() bool { + return true +} + type basicAuthRoundTripper struct { base http.RoundTripper authData *ClientAuthSettings @@ -231,5 +246,13 @@ func (ba *basicAuth) RoundTripper(base http.RoundTripper) (http.RoundTripper, er } func (ba *basicAuth) PerRPCCredentials() (creds.PerRPCCredentials, error) { - return nil, nil + if strings.Contains(ba.clientAuth.Username, ":") { + return nil, errInvalidFormat + } + encoded := base64.StdEncoding.EncodeToString([]byte(ba.clientAuth.Username + ":" + ba.clientAuth.Password)) + return &perRPCAuth{ + metadata: map[string]string{ + "authorization": encoded, + }, + }, nil } diff --git a/extension/basicauthextension/extension_test.go b/extension/basicauthextension/extension_test.go index 75680346598b..eb622b96c326 100644 --- a/extension/basicauthextension/extension_test.go +++ b/extension/basicauthextension/extension_test.go @@ -214,6 +214,20 @@ func TestBasicAuth_ServerInvalid(t *testing.T) { assert.Error(t, err) } +func TestPerRPCAuth(t *testing.T) { + metadata := map[string]string{ + "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmR4eHg=", + } + + rpcAuth := &perRPCAuth{metadata: metadata} + md, err := rpcAuth.GetRequestMetadata(context.Background()) + assert.NoError(t, err) + assert.Equal(t, md, metadata) + + ok := rpcAuth.RequireTransportSecurity() + assert.True(t, ok) +} + type mockRoundTripper struct{} func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { @@ -253,6 +267,20 @@ func TestBasicAuth_ClientValid(t *testing.T) { resp, err := c.RoundTrip(&http.Request{Header: orgHeaders}) assert.NoError(t, err) assert.Equal(t, expectedHeaders, resp.Header) + + credential, err := ext.PerRPCCredentials() + + assert.NoError(t, err) + assert.NotNil(t, credential) + + md, err := credential.GetRequestMetadata(context.Background()) + expectedMd := map[string]string{ + "authorization": fmt.Sprintf("Basic %s", authCreds), + } + assert.Equal(t, md, expectedMd) + assert.NoError(t, err) + assert.True(t, credential.RequireTransportSecurity()) + assert.Nil(t, ext.Shutdown(context.Background())) } @@ -281,6 +309,8 @@ func TestBasicAuth_ClientInValid(t *testing.T) { base := &mockRoundTripper{} _, err = ext.RoundTripper(base) assert.Error(t, err) - }) + _, err = ext.PerRPCCredentials() + assert.Error(t, err) + }) } From a83bf79d2aea15b55d77c5275e8bd31952aaf023 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Fri, 15 Apr 2022 14:06:06 +0530 Subject: [PATCH 10/12] review comments and minor fixes --- extension/basicauthextension/README.md | 15 +++++++++------ extension/basicauthextension/extension.go | 13 +------------ extension/basicauthextension/extension_test.go | 2 +- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/extension/basicauthextension/README.md b/extension/basicauthextension/README.md index b6250ce7ee54..ebe00d139a58 100644 --- a/extension/basicauthextension/README.md +++ b/extension/basicauthextension/README.md @@ -1,6 +1,6 @@ # Basic Authenticator -This extension implements both `configauth.ServerAuthenticator` and `configauth.ClientAuthenticator` to authenticate clients and servers using HTTP Basic Authentication. The authenticator type has to be set to `basicauth`. +This extension implements both `configauth.ServerAuthenticator` and `configauth.ClientAuthenticator` to authenticate clients and servers using Basic Authentication. The authenticator type has to be set to `basicauth`. When used as ServerAuthenticator, if the authentication is successful `client.Info.Auth` will expose the following attributes: @@ -13,7 +13,8 @@ The following are the configuration options: - `htpasswd.file`: The path to the htpasswd file. - `htpasswd.inline`: The htpasswd file inline content. -- `client_auth`: Single username password combination in the form of `username:password` for client authentication. +- `client_auth.username`: Username to use for client authentication. +- `client_auth.password`: Password to use for client authentication. To configure the extension as a server authenticator, either one of `htpasswd.file` or `htpasswd.inline` has to be set. If both are configured, `htpasswd.inline` credentials take precedence. @@ -31,7 +32,9 @@ extensions: ${BASIC_AUTH_USERNAME}:${BASIC_AUTH_PASSWORD} basicauth/client: - client_auth: username:password + client_auth: + username: username + password: password receivers: otlp: @@ -43,9 +46,9 @@ receivers: processors: exporters: - otlphttp: + otlp: auth: - authenticator: basicauth/client + authenticator: basicauth/client service: extensions: [basicauth/server, basicauth/client] @@ -53,5 +56,5 @@ service: traces: receivers: [otlp] processors: [] - exporters: [otlphttp] + exporters: [otlp] ``` diff --git a/extension/basicauthextension/extension.go b/extension/basicauthextension/extension.go index 0b99cb705403..b93bbf7e6900 100644 --- a/extension/basicauthextension/extension.go +++ b/extension/basicauthextension/extension.go @@ -53,8 +53,6 @@ func newClientAuthExtension(cfg *Config) (configauth.ClientAuthenticator, error) clientAuth: cfg.ClientAuth, } return configauth.NewClientAuthenticator( - configauth.WithClientStart(ba.clientStart), - configauth.WithClientShutdown(ba.shutdown), configauth.WithClientRoundTripper(ba.RoundTripper), configauth.WithPerRPCCredentials(ba.PerRPCCredentials), ), nil @@ -71,15 +69,10 @@ func newServerAuthExtension(cfg *Config) (configauth.ServerAuthenticator, error) } return configauth.NewServerAuthenticator( configauth.WithStart(ba.serverStart), - configauth.WithShutdown(ba.shutdown), configauth.WithAuthenticate(ba.authenticate), ), nil } -func (ba *basicAuth) clientStart(_ context.Context, _ component.Host) error { - return nil -} - func (ba *basicAuth) serverStart(ctx context.Context, host component.Host) error { var rs []io.Reader @@ -109,10 +102,6 @@ func (ba *basicAuth) serverStart(ctx context.Context, host component.Host) error return nil } -func (ba *basicAuth) shutdown(ctx context.Context) error { - return nil -} - func (ba *basicAuth) authenticate(ctx context.Context, headers map[string][]string) (context.Context, error) { auth := getAuthHeader(headers) if auth == "" { @@ -252,7 +241,7 @@ func (ba *basicAuth) PerRPCCredentials() (creds.PerRPCCredentials, error) { encoded := base64.StdEncoding.EncodeToString([]byte(ba.clientAuth.Username + ":" + ba.clientAuth.Password)) return &perRPCAuth{ metadata: map[string]string{ - "authorization": encoded, + "authorization": fmt.Sprintf("Basic %s", encoded), }, }, nil } diff --git a/extension/basicauthextension/extension_test.go b/extension/basicauthextension/extension_test.go index 4aadfa32cabb..569367c43beb 100644 --- a/extension/basicauthextension/extension_test.go +++ b/extension/basicauthextension/extension_test.go @@ -304,7 +304,7 @@ func TestBasicAuth_ClientInvalid(t *testing.T) { require.NotNil(t, ext) require.NoError(t, err) - require.Nil(t, ext.Start(context.Background(), componenttest.NewNopHost())) + require.NoError(t, ext.Start(context.Background(), componenttest.NewNopHost())) base := &mockRoundTripper{} _, err = ext.RoundTripper(base) From 2e12e9e428001f14021273df89ff489278901da8 Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Tue, 19 Apr 2022 11:58:04 +0530 Subject: [PATCH 11/12] address comments and make func signatures private --- extension/basicauthextension/config.go | 4 ++-- extension/basicauthextension/extension.go | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/extension/basicauthextension/config.go b/extension/basicauthextension/config.go index bed12f40e25e..1ff8c3b5bc93 100644 --- a/extension/basicauthextension/config.go +++ b/extension/basicauthextension/config.go @@ -22,7 +22,7 @@ import ( var ( errNoCredentialSource = errors.New("no credential source provided") - errMultipleAuthenticator = errors.New("only one of `htpasswd` or `client_auth` can be specified") + errMultipleAuthenticators = errors.New("only one of `htpasswd` or `client_auth` can be specified") ) type HtpasswdSettings struct { @@ -53,7 +53,7 @@ func (cfg *Config) Validate() error { clientCondition := cfg.ClientAuth != nil if serverCondition && clientCondition { - return errMultipleAuthenticator + return errMultipleAuthenticators } if !serverCondition && !clientCondition { diff --git a/extension/basicauthextension/extension.go b/extension/basicauthextension/extension.go index b93bbf7e6900..8f7801cbdc58 100644 --- a/extension/basicauthextension/extension.go +++ b/extension/basicauthextension/extension.go @@ -53,8 +53,8 @@ func newClientAuthExtension(cfg *Config) (configauth.ClientAuthenticator, error) clientAuth: cfg.ClientAuth, } return configauth.NewClientAuthenticator( - configauth.WithClientRoundTripper(ba.RoundTripper), - configauth.WithPerRPCCredentials(ba.PerRPCCredentials), + configauth.WithClientRoundTripper(ba.roundTripper), + configauth.WithPerRPCCredentials(ba.perRPCCredentials), ), nil } @@ -199,6 +199,7 @@ func (*authData) GetAttributeNames() []string { return []string{"username", "raw"} } +// perRPCAuth is a gRPC credentials.PerRPCCredentials implementation that returns an 'authorization' header. type perRPCAuth struct { metadata map[string]string } @@ -224,7 +225,7 @@ func (b *basicAuthRoundTripper) RoundTrip(request *http.Request) (*http.Response return b.base.RoundTrip(newRequest) } -func (ba *basicAuth) RoundTripper(base http.RoundTripper) (http.RoundTripper, error) { +func (ba *basicAuth) roundTripper(base http.RoundTripper) (http.RoundTripper, error) { if strings.Contains(ba.clientAuth.Username, ":") { return nil, errInvalidFormat } @@ -234,7 +235,7 @@ func (ba *basicAuth) RoundTripper(base http.RoundTripper) (http.RoundTripper, er }, nil } -func (ba *basicAuth) PerRPCCredentials() (creds.PerRPCCredentials, error) { +func (ba *basicAuth) perRPCCredentials() (creds.PerRPCCredentials, error) { if strings.Contains(ba.clientAuth.Username, ":") { return nil, errInvalidFormat } From 9d3312c72d70feecc970e737306d2b270aba814d Mon Sep 17 00:00:00 2001 From: Neelay Upadhyaya Date: Tue, 19 Apr 2022 14:06:09 +0530 Subject: [PATCH 12/12] gofmt lint error fix --- extension/basicauthextension/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/basicauthextension/config.go b/extension/basicauthextension/config.go index 1ff8c3b5bc93..ea6de6c5a44a 100644 --- a/extension/basicauthextension/config.go +++ b/extension/basicauthextension/config.go @@ -21,7 +21,7 @@ import ( ) var ( - errNoCredentialSource = errors.New("no credential source provided") + errNoCredentialSource = errors.New("no credential source provided") errMultipleAuthenticators = errors.New("only one of `htpasswd` or `client_auth` can be specified") )