-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
This PR ports the client authenticator interfaces from PR #3128 in a piece meal fashion. The interfaces are currently not used by any client configurations and are published for reviewing only. Plan is to modify ToClient and ToDialOptions apis once all the clients are prepared per #3287 (core and contrib side as well). Link to tracking Issue: #3287 #3282 Testing: Unit tests, [manual test described (for only oidc)](#3128 (comment))
- Loading branch information
1 parent
4a7beef
commit 7cd868d
Showing
13 changed files
with
316 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 configauth | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
|
||
"google.golang.org/grpc/credentials" | ||
|
||
"go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config" | ||
) | ||
|
||
// ClientAuthenticator is an Extension that can be used as an authenticator for the configauth.Authentication option. | ||
// Authenticators are then included as part of OpenTelemetry Collector builds and can be referenced by their | ||
// names from the Authentication configuration. | ||
type ClientAuthenticator interface { | ||
component.Extension | ||
} | ||
|
||
// HTTPClientAuthenticator is a ClientAuthenticator that can be used as an authenticator | ||
// for the configauth.Authentication option for HTTP clients. | ||
type HTTPClientAuthenticator interface { | ||
ClientAuthenticator | ||
RoundTripper(base http.RoundTripper) (http.RoundTripper, error) | ||
} | ||
|
||
// GRPCClientAuthenticator is a ClientAuthenticator that can be used as an authenticator for | ||
// the configauth.Authentication option for gRPC clients. | ||
type GRPCClientAuthenticator interface { | ||
ClientAuthenticator | ||
PerRPCCredentials() (credentials.PerRPCCredentials, error) | ||
} | ||
|
||
// GetHTTPClientAuthenticator attempts to select the appropriate HTTPClientAuthenticator from the list of extensions, | ||
// based on the component id of the extension. If an authenticator is not found, an error is returned. | ||
// This should be only used by HTTP clients. | ||
func GetHTTPClientAuthenticator(extensions map[config.ComponentID]component.Extension, | ||
componentID config.ComponentID) (HTTPClientAuthenticator, error) { | ||
for id, ext := range extensions { | ||
if id == componentID { | ||
if auth, ok := ext.(HTTPClientAuthenticator); ok { | ||
return auth, nil | ||
} | ||
return nil, fmt.Errorf("requested authenticator is not for HTTP clients") | ||
} | ||
} | ||
return nil, fmt.Errorf("failed to resolve authenticator %q: %w", componentID.String(), errAuthenticatorNotFound) | ||
} | ||
|
||
// GetGRPCClientAuthenticator attempts to select the appropriate GRPCClientAuthenticator from the list of extensions, | ||
// based on the component id of the extension. If an authenticator is not found, an error is returned. | ||
// This should only be used by gRPC clients. | ||
func GetGRPCClientAuthenticator(extensions map[config.ComponentID]component.Extension, | ||
componentID config.ComponentID) (GRPCClientAuthenticator, error) { | ||
for id, ext := range extensions { | ||
if id == componentID { | ||
if auth, ok := ext.(GRPCClientAuthenticator); ok { | ||
return auth, nil | ||
} | ||
return nil, fmt.Errorf("requested authenticator is not for gRPC clients") | ||
} | ||
} | ||
return nil, fmt.Errorf("failed to resolve authenticator %q: %w", componentID.String(), errAuthenticatorNotFound) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// 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 configauth | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
|
||
"google.golang.org/grpc/credentials" | ||
|
||
"go.opentelemetry.io/collector/component" | ||
) | ||
|
||
var ( | ||
_ HTTPClientAuthenticator = (*MockClientAuthenticator)(nil) | ||
_ GRPCClientAuthenticator = (*MockClientAuthenticator)(nil) | ||
errMockError = errors.New("mock Error") | ||
) | ||
|
||
// MockClientAuthenticator provides a mock implementation of GRPCClientAuthenticator and HTTPClientAuthenticator interfaces | ||
type MockClientAuthenticator struct { | ||
ResultRoundTripper http.RoundTripper | ||
ResultPerRPCCredentials credentials.PerRPCCredentials | ||
MustError bool | ||
} | ||
|
||
// Start for the MockClientAuthenticator does nothing | ||
func (m *MockClientAuthenticator) Start(ctx context.Context, host component.Host) error { | ||
return nil | ||
} | ||
|
||
// Shutdown for the MockClientAuthenticator does nothing | ||
func (m *MockClientAuthenticator) Shutdown(ctx context.Context) error { | ||
return nil | ||
} | ||
|
||
// RoundTripper for the MockClientAuthenticator either returns error if the mock authenticator is forced to or | ||
// returns the supplied resultRoundTripper. | ||
func (m *MockClientAuthenticator) RoundTripper(base http.RoundTripper) (http.RoundTripper, error) { | ||
if m.MustError { | ||
return nil, errMockError | ||
} | ||
return m.ResultRoundTripper, nil | ||
} | ||
|
||
// PerRPCCredentials for the MockClientAuthenticator either returns error if the mock authenticator is forced to or | ||
// returns the supplied resultPerRPCCredentials. | ||
func (m *MockClientAuthenticator) PerRPCCredentials() (credentials.PerRPCCredentials, error) { | ||
if m.MustError { | ||
return nil, errMockError | ||
} | ||
return m.ResultPerRPCCredentials, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// 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 configauth | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"google.golang.org/grpc/credentials" | ||
) | ||
|
||
func TestNilStartAndShutdown(t *testing.T) { | ||
// prepare | ||
m := &MockClientAuthenticator{} | ||
|
||
// test and verify | ||
origCtx := context.Background() | ||
|
||
err := m.Start(origCtx, nil) | ||
assert.NoError(t, err) | ||
|
||
err = m.Shutdown(origCtx) | ||
assert.NoError(t, err) | ||
} | ||
|
||
type customRoundTripper struct{} | ||
|
||
func (c *customRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { | ||
return nil, nil | ||
} | ||
|
||
func TestMockRoundTripper(t *testing.T) { | ||
testcases := []struct { | ||
name string | ||
expectedErr bool | ||
clientAuth MockClientAuthenticator | ||
}{ | ||
{ | ||
name: "no_error", | ||
expectedErr: false, | ||
clientAuth: MockClientAuthenticator{ | ||
ResultRoundTripper: &customRoundTripper{}, | ||
MustError: false, | ||
}, | ||
}, | ||
{ | ||
name: "error", | ||
expectedErr: true, | ||
clientAuth: MockClientAuthenticator{ | ||
ResultRoundTripper: &customRoundTripper{}, | ||
MustError: true, | ||
}, | ||
}, | ||
} | ||
|
||
for _, testcase := range testcases { | ||
t.Run(testcase.name, func(t *testing.T) { | ||
tripper, err := testcase.clientAuth.RoundTripper(nil) | ||
if testcase.expectedErr { | ||
assert.Error(t, err) | ||
return | ||
} | ||
assert.NotNil(t, tripper) | ||
assert.NoError(t, err) | ||
// check if the resultant tripper is indeed the one provided | ||
_, ok := tripper.(*customRoundTripper) | ||
assert.True(t, ok) | ||
}) | ||
} | ||
} | ||
|
||
type customPerRPCCredentials struct{} | ||
|
||
var _ credentials.PerRPCCredentials = (*customPerRPCCredentials)(nil) | ||
|
||
func (c *customPerRPCCredentials) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { | ||
return nil, nil | ||
} | ||
|
||
func (c *customPerRPCCredentials) RequireTransportSecurity() bool { | ||
return true | ||
} | ||
|
||
func TestMockPerRPCCredential(t *testing.T) { | ||
testcases := []struct { | ||
name string | ||
expectedErr bool | ||
clientAuth MockClientAuthenticator | ||
}{ | ||
{ | ||
name: "no_error", | ||
expectedErr: false, | ||
clientAuth: MockClientAuthenticator{ | ||
ResultPerRPCCredentials: &customPerRPCCredentials{}, | ||
MustError: false, | ||
}, | ||
}, | ||
{ | ||
name: "error", | ||
expectedErr: true, | ||
clientAuth: MockClientAuthenticator{ | ||
ResultPerRPCCredentials: &customPerRPCCredentials{}, | ||
MustError: true, | ||
}, | ||
}, | ||
} | ||
|
||
for _, testcase := range testcases { | ||
t.Run(testcase.name, func(t *testing.T) { | ||
credential, err := testcase.clientAuth.PerRPCCredentials() | ||
if err != nil { | ||
return | ||
} | ||
if testcase.expectedErr { | ||
assert.Error(t, err) | ||
return | ||
} | ||
assert.NotNil(t, credential) | ||
assert.NoError(t, err) | ||
// check if the resultant tripper is indeed the one provided | ||
_, ok := credential.(*customPerRPCCredentials) | ||
assert.True(t, ok) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.