Skip to content

Commit

Permalink
feat: adding support to error handlers (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeandroFranciscato authored Apr 25, 2023
1 parent b2b00cd commit 55619ed
Show file tree
Hide file tree
Showing 28 changed files with 470 additions and 293 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ kube-builder: &install-kube-builder
sudo mv /tmp/kubebuilder_2.3.2_${os}_${arch} /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin
golaing_image: &golang_image
image: circleci/golang:1.16.12
image: circleci/golang:1.17.5
version: 2
jobs:
build:
Expand Down Expand Up @@ -44,8 +44,8 @@ jobs:
name: Update golang
command: |
sudo rm -rf /usr/local/go/
curl -LO https://go.dev/dl/go1.16.12.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.16.12.linux-amd64.tar.gz
curl -LO https://go.dev/dl/go1.17.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz
sudo echo "export PATH=$PATH:/usr/local/go/bin" >> $HOME/.profile
go version
- run:
Expand Down
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
CHANGELOG.md
CONTRIBUTING.md
.github/pull_request_template.md
api/v1alpha1/tests/*
tests/integration/files/*
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.16 as builder
FROM golang:1.17 as builder
WORKDIR /go/src/app
COPY . .
RUN apt update &&\
Expand Down
4 changes: 3 additions & 1 deletion api/v1alpha1/defaults.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package v1alpha1
Expand All @@ -7,11 +7,13 @@ var (
DefaultAuthenticatorsAvailable = [...]string{"noop", "unauthorized", "anonymous", "cookie_session", "oauth2_client_credentials", "oauth2_introspection", "jwt", "bearer_token"}
DefaultAuthorizersAvailable = [...]string{"allow", "deny", "keto_engine_acp_ory", "remote", "remote_json"}
DefaultMutatorsAvailable = [...]string{"noop", "id_token", "header", "cookie", "hydrator"}
DefaultErrorsAvailable = [...]string{"json", "redirect", "www_authenticate"}
)

const (
AuthenticatorsAvailableEnv = "authenticatorsAvailable"
AuthorizersAvailableEnv = "authorizersAvailable"
MutatorsAvailableEnv = "mutatorsAvailable"
ErrorsAvailableEnv = "errorsAvailable"
RulesFileNameRegexp = "\\A[-._a-zA-Z0-9]+\\z"
)
2 changes: 1 addition & 1 deletion api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

// Package v1alpha1 contains API Schema definitions for the oathkeeper v1alpha1 API group
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/json.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package v1alpha1
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/rule_json.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package v1alpha1
Expand Down
8 changes: 7 additions & 1 deletion api/v1alpha1/rule_types.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package v1alpha1
Expand Down Expand Up @@ -52,6 +52,7 @@ type RuleSpec struct {
Authenticators []*Authenticator `json:"authenticators,omitempty"`
Authorizer *Authorizer `json:"authorizer,omitempty"`
Mutators []*Mutator `json:"mutators,omitempty"`
Errors []*Error `json:"errors,omitempty"`
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:Pattern=[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
Expand Down Expand Up @@ -112,6 +113,11 @@ type Mutator struct {
*Handler `json:",inline"`
}

// Error represents a handler that is responsible for executing logic when an error happens.
type Error struct {
*Handler `json:",inline"`
}

// Handler represents an Oathkeeper routine that operates on incoming requests. It is used to either validate a request (Authenticator, Authorizer) or modify it (Mutator).
type Handler struct {
// Name is the name of a handler
Expand Down
201 changes: 28 additions & 173 deletions api/v1alpha1/rule_types_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright © 2022 Ory Corp
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package v1alpha1

import (
_ "embed"
"fmt"
"testing"

Expand All @@ -14,168 +15,14 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)

var (
template = `[
{
"upstream": {
"url": "http://my-backend-service1",
"strip_path": "/api/v1",
"preserve_host": true
},
"id": "foo1.default",
"match": {
"url": "http://my-app/some-route1<.*>",
"methods": [
"GET",
"POST"
]
},
"authenticators": [
{
"handler": "handler1",
"config": {
"key1": "val1"
}
}
],
"authorizer": {
"handler": "deny"
},
"mutators": [
{
"handler": "handler1",
"config": {
"key1": "val1"
}
},
{
"handler": "handler2",
"config": {
"key1": [
"val1",
"val2",
"val3"
]
}
}
]
},
{
"upstream": {
"url": "http://my-backend-service2",
"preserve_host": false
},
"id": "foo2.default",
"match": {
"url": "http://my-app/some-route2",
"methods": [
"GET",
"POST"
]
},
"authenticators": [
{
"handler": "handler1",
"config": {
"key1": "val1"
}
},
{
"handler": "handler2",
"config": {
"key1": [
"val1",
"val2",
"val3"
]
}
}
],
"authorizer": {
"handler": "deny"
},
"mutators": [
{
"handler": "noop"
}
]
},
{
"upstream": {
"url": "http://my-backend-service3",
"preserve_host": false
},
"id": "foo3.default",
"match": {
"url": "http://my-app/some-route3",
"methods": [
"GET",
"POST"
]
},
"authenticators": [
{
"handler": "unauthorized"
}
],
"authorizer": {
"handler": "handler1",
"config": {
"key1": "val1"
}
},
"mutators": [
{
"handler": "noop"
}
]
},
{
"upstream": {
"url": "",
"preserve_host": false
},
"id": "fooNoUpstream.default",
"match": {
"url": "http://my-app/some-route3",
"methods": [
"GET",
"POST"
]
},
"authenticators": [
{
"handler": "unauthorized"
}
],
"authorizer": {
"handler": "handler1",
"config": {
"key1": "val1"
}
},
"mutators": [
{
"handler": "noop"
}
]
}
]`

sampleConfig = `{
"key1": "val1"
}
`

sampleConfig2 = `{
"key1": [
"val1",
"val2",
"val3"
]
}
`
)
//go:embed tests/rules.json
var template string

//go:embed tests/sample_config.json
var sampleConfig string

//go:embed tests/sample_config2.json
var sampleConfig2 string

func TestToOathkeeperRules(t *testing.T) {

Expand Down Expand Up @@ -212,7 +59,9 @@ func TestToOathkeeperRules(t *testing.T) {
newBoolPtr(true),
[]*Authenticator{{h1}},
nil,
[]*Mutator{{h1}, {h2}})
[]*Mutator{{h1}, {h2}},
[]*Error{{h1}},
)

rule2 := newRule(
"foo2",
Expand All @@ -224,7 +73,8 @@ func TestToOathkeeperRules(t *testing.T) {
newBoolPtr(false),
[]*Authenticator{{h1}, {h2}},
nil,
nil)
nil,
[]*Error{{h2}})

rule3 := newRule(
"foo3",
Expand All @@ -236,7 +86,8 @@ func TestToOathkeeperRules(t *testing.T) {
nil,
nil,
&Authorizer{h1},
nil)
nil,
[]*Error{{h1}, {h2}})

rule4 := newRule(
"fooNoUpstream",
Expand All @@ -248,6 +99,7 @@ func TestToOathkeeperRules(t *testing.T) {
nil,
nil,
&Authorizer{h1},
nil,
nil)

list.Items = []Rule{*rule1, *rule2, *rule3, *rule4}
Expand Down Expand Up @@ -278,7 +130,7 @@ func TestToRuleJson(t *testing.T) {

{
"If no handlers have been specified, it should generate an ID and add default values for missing handlers",
newStaticRule(nil, nil, nil),
newStaticRule(nil, nil, nil, nil),
func(r *RuleJSON) {
assert.Equal(unauthorizedHandler, r.Authenticators[0].Handler)
assert.Equal(denyHandler, r.Authorizer.Handler)
Expand All @@ -287,7 +139,7 @@ func TestToRuleJson(t *testing.T) {
},
{
"If one handler type has been provided, it should generate an ID, rewrite the provided handler and add default values for missing handlers",
newStaticRule(nil, nil, []*Mutator{{testHandler}}),
newStaticRule(nil, nil, []*Mutator{{testHandler}}, nil),
func(r *RuleJSON) {
assert.Equal(unauthorizedHandler, r.Authenticators[0].Handler)
assert.Equal(denyHandler, r.Authorizer.Handler)
Expand All @@ -296,7 +148,7 @@ func TestToRuleJson(t *testing.T) {
},
{
"If all handler types are defined, it should generate an ID and rewrite the handlers",
newStaticRule([]*Authenticator{{testHandler}}, &Authorizer{testHandler}, []*Mutator{{testHandler}}),
newStaticRule([]*Authenticator{{testHandler}}, &Authorizer{testHandler}, []*Mutator{{testHandler}}, nil),
func(r *RuleJSON) {
assert.Equal(testHandler, r.Authenticators[0].Handler)
assert.Equal(testHandler, r.Authorizer.Handler)
Expand All @@ -305,13 +157,14 @@ func TestToRuleJson(t *testing.T) {
},
{
"if multiple authentication and/or mutation handlers have been provided, it should rewrite all of them",
newStaticRule([]*Authenticator{{testHandler}, {testHandler2}}, nil, []*Mutator{{testHandler}, {testHandler2}}),
newStaticRule([]*Authenticator{{testHandler}, {testHandler2}}, nil, []*Mutator{{testHandler}, {testHandler2}}, []*Error{{testHandler}}),
func(r *RuleJSON) {
assert.Equal(testHandler, r.Authenticators[0].Handler)
assert.Equal(testHandler2, r.Authenticators[1].Handler)
assert.Equal(testHandler, r.Mutators[0].Handler)
assert.Equal(testHandler2, r.Mutators[1].Handler)
assert.Equal(denyHandler, r.Authorizer.Handler)
assert.Equal(testHandler, r.Errors[0].Handler)
},
},
} {
Expand Down Expand Up @@ -351,6 +204,7 @@ func TestValidateWith(t *testing.T) {
newBoolPtr(true),
nil,
nil,
nil,
nil)

var validationConfig = validation.Config{
Expand Down Expand Up @@ -424,11 +278,11 @@ func TestFilterNotValid(t *testing.T) {
})
}

func newStaticRule(authenticators []*Authenticator, authorizer *Authorizer, mutators []*Mutator) *Rule {
return newRule("r1", "test", "", "", newStringPtr(""), nil, newBoolPtr(false), authenticators, authorizer, mutators)
func newStaticRule(authenticators []*Authenticator, authorizer *Authorizer, mutators []*Mutator, errors []*Error) *Rule {
return newRule("r1", "test", "", "", newStringPtr(""), nil, newBoolPtr(false), authenticators, authorizer, mutators, errors)
}

func newRule(name, namespace, upstreamURL, matchURL string, stripURLPath, configMapName *string, preserveURLHost *bool, authenticators []*Authenticator, authorizer *Authorizer, mutators []*Mutator) *Rule {
func newRule(name, namespace, upstreamURL, matchURL string, stripURLPath, configMapName *string, preserveURLHost *bool, authenticators []*Authenticator, authorizer *Authorizer, mutators []*Mutator, errors []*Error) *Rule {

spec := RuleSpec{
Upstream: &Upstream{
Expand All @@ -443,6 +297,7 @@ func newRule(name, namespace, upstreamURL, matchURL string, stripURLPath, config
Authenticators: authenticators,
Authorizer: authorizer,
Mutators: mutators,
Errors: errors,
ConfigMapName: configMapName,
}

Expand Down
Loading

0 comments on commit 55619ed

Please sign in to comment.