Skip to content

Commit

Permalink
Added support for authentication processor
Browse files Browse the repository at this point in the history
Includes an initial support for OIDC authenticator.

Closes #1424

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
  • Loading branch information
jpkrohling committed Sep 3, 2020
1 parent 95389af commit d2ab657
Show file tree
Hide file tree
Showing 17 changed files with 1,517 additions and 3 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/census-instrumentation/opencensus-proto v0.3.0
github.com/client9/misspell v0.3.4
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.5.0+incompatible // indirect
github.com/go-kit/kit v0.10.0
Expand All @@ -34,6 +35,7 @@ require (
github.com/orijtech/prometheus-go-metrics-exporter v0.0.5
github.com/ory/go-acc v0.2.6
github.com/pavius/impi v0.0.3
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v1.7.1
github.com/prometheus/common v0.11.1
github.com/prometheus/prometheus v1.8.2-0.20200626085723-c448ada63d83
Expand All @@ -60,6 +62,7 @@ require (
google.golang.org/grpc v1.31.0
google.golang.org/grpc/examples v0.0.0-20200728065043-dfc0c05b2da9 // indirect
google.golang.org/protobuf v1.25.0
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.3.0
honnef.co/go/tools v0.0.1-2020.1.5
)
121 changes: 118 additions & 3 deletions go.sum

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions processor/authenticationprocessor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Authentication Processor

* Supported pipeline types: traces
* Status: in development

This processor authenticates the incoming traces by extracting the authentication data from the context
and verifying the bearer token with the specified provider.

Currently, only bearer token authentication is supported, added as part of `PerRPC` gRPC authentication.
It requires the gRPC client to send a header named `authorization` in line with the equivalent HTTP/2 header.

Examples:
```yaml
processors:
authentication:
oidc:
issuer_url: https://auth.example.com/
issuer_ca_path: /etc/pki/tls/cert.pem
client_id: my-oidc-client
username_claim: email
```
Refer to [config.yaml](./testdata/config.yaml) for detailed examples on using the processor.
27 changes: 27 additions & 0 deletions processor/authenticationprocessor/authenticator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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 authenticationprocessor

import (
"context"

"go.opentelemetry.io/collector/component"
)

type authenticator interface {
authenticate(context.Context) (bool, error)
start(context.Context, component.Host) error
shutdown(context.Context) error
}
52 changes: 52 additions & 0 deletions processor/authenticationprocessor/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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 authenticationprocessor

import (
"go.opentelemetry.io/collector/config/configmodels"
)

// Config is the configuration for the processor.
type Config struct {
configmodels.ProcessorSettings `mapstructure:",squash"`

// OIDC configures this processor to use the given OIDC provider as the backend for the authentication mechanism.
// Required.
OIDC *OIDC `mapstructure:"oidc"`
}

// OIDC defines the OpenID Connect properties for this processor
type OIDC struct {
// IssuerURL is the base URL for the OIDC provider.
// Required.
IssuerURL string `mapstructure:"issuer_url"`

// Audience of the token, used during the verification.
// For example: "https://accounts.google.com" or "https://login.salesforce.com".
// Required.
Audience string `mapstructure:"audience"`

// The local path for the issuer CA's TLS server cert.
// Optional.
IssuerCAPath string `mapstructure:"issuer_ca_path"`

// The claim to use as the username, in case the token's 'sub' isn't the suitable source.
// Optional.
UsernameClaim string `mapstructure:"username_claim"`

// The claim that holds the subject's group membership information.
// Optional.
GroupsClaim string `mapstructure:"groups_claim"`
}
15 changes: 15 additions & 0 deletions processor/authenticationprocessor/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 authenticationprocessor
69 changes: 69 additions & 0 deletions processor/authenticationprocessor/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 authenticationprocessor

import (
"context"
"errors"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config/configmodels"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/processor/processorhelper"
)

const (
// typeStr is the value of "type" for this processor in the configuration.
typeStr configmodels.Type = "authentication"
)

var (
errNoOIDCProvided = errors.New("no OIDC information provided")
errNoClientIDProvided = errors.New("no ClientID provided for the OIDC configuration")
errNoIssuerURL = errors.New("no IssuerURL provided for the OIDC configuration")
)

// NewFactory creates a factory for the routing processor.
func NewFactory() component.ProcessorFactory {
return processorhelper.NewFactory(
typeStr,
createDefaultConfig,
processorhelper.WithTraces(createTraceProcessor),
)
}

func createDefaultConfig() configmodels.Processor {
return &Config{
ProcessorSettings: configmodels.ProcessorSettings{
TypeVal: typeStr,
NameVal: string(typeStr),
},
}
}

func createTraceProcessor(_ context.Context, params component.ProcessorCreateParams, cfg configmodels.Processor, nextConsumer consumer.TraceConsumer) (component.TraceProcessor, error) {
oCfg := cfg.(*Config)
if oCfg.OIDC == nil {
return nil, errNoOIDCProvided
}
if oCfg.OIDC.Audience == "" {
return nil, errNoClientIDProvided
}
if oCfg.OIDC.IssuerURL == "" {
return nil, errNoIssuerURL
}

return newAuthenticationProcessor(params.Logger, nextConsumer, *oCfg)
}
94 changes: 94 additions & 0 deletions processor/authenticationprocessor/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// 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 authenticationprocessor

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/exporter/exportertest"
)

func TestCreateTestProcessor(t *testing.T) {
// prepare
logger, err := zap.NewDevelopment()
require.NoError(t, err)

f := NewFactory()
c := f.CreateDefaultConfig().(*Config)

c.OIDC = &OIDC{
Audience: "unit-tests",
IssuerURL: "http://example.com/",
}
params := component.ProcessorCreateParams{Logger: logger}

// test
p, err := f.CreateTraceProcessor(context.Background(), params, exportertest.NewNopTraceExporter(), c)

// verify
assert.NoError(t, err)
assert.NotNil(t, p)
}

func TestMissingOIDCParameters(t *testing.T) {
for _, tt := range []struct {
casename string
config *Config
expectedErr error
}{
{
"no-oidc",
NewFactory().CreateDefaultConfig().(*Config),
errNoOIDCProvided,
},
{
"no-client-id",
&Config{
OIDC: &OIDC{
IssuerURL: "http://example.com/",
},
},
errNoClientIDProvided,
},
{
"no-issuer-url",
&Config{
OIDC: &OIDC{
Audience: "unit-tests",
},
},
errNoIssuerURL,
},
} {
t.Run(tt.casename, func(t *testing.T) {
// prepare
f := NewFactory()
params := component.ProcessorCreateParams{}

// test
p, err := f.CreateTraceProcessor(context.Background(), params, nil, tt.config)

// verify
assert.Equal(t, err, tt.expectedErr)
assert.Nil(t, p)
})
}
}
40 changes: 40 additions & 0 deletions processor/authenticationprocessor/mock_authenticator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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 authenticationprocessor

import (
"context"

"go.opentelemetry.io/collector/component"
)

var _ authenticator = (*mockAuthenticator)(nil)

type mockAuthenticator struct {
succeed bool
err error
startErr error
shutdownErr error
}

func (m *mockAuthenticator) authenticate(context.Context) (bool, error) {
return m.succeed, m.err
}
func (m *mockAuthenticator) start(context.Context, component.Host) error {
return m.startErr
}
func (m *mockAuthenticator) shutdown(context.Context) error {
return m.shutdownErr
}
Loading

0 comments on commit d2ab657

Please sign in to comment.