Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds AuthenticationFilter Support to Kubernetes Provider #791

Merged
merged 1 commit into from
Dec 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ release-artifacts/

# Outputs
coverage.xml
cover.out
arkodg marked this conversation as resolved.
Show resolved Hide resolved

# `go mod vendor`
vendor/
Expand Down
11 changes: 8 additions & 3 deletions api/v1alpha1/authenticationfilter_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
// AuthenticationFilterKind is the name of the AuthenticationFilter kind.
AuthenticationFilterKind = "AuthenticationFilter"
)

//+kubebuilder:object:root=true

type AuthenticationFilter struct {
Expand Down Expand Up @@ -114,13 +119,13 @@ type RemoteJWKS struct {

//+kubebuilder:object:root=true

// AuthenticationList contains a list of Authentication.
type AuthenticationList struct {
// AuthenticationFilterList contains a list of AuthenticationFilter.
type AuthenticationFilterList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AuthenticationFilter `json:"items"`
}

func init() {
SchemeBuilder.Register(&AuthenticationFilter{}, &AuthenticationList{})
SchemeBuilder.Register(&AuthenticationFilter{}, &AuthenticationFilterList{})
}
48 changes: 24 additions & 24 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions internal/envoygateway/scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"

"github.com/envoyproxy/gateway/api/config/v1alpha1"
egcfgv1a1 "github.com/envoyproxy/gateway/api/config/v1alpha1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we combine these two into one ?

Copy link
Contributor Author

@danehans danehans Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we keep them separate to simplify moving the Gateway API extensions, e.g. AuthenticationFilter, out of EG into a separate repo in the future? If we decide to remove the config API group, I think that should be done in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying to highlight the fact that current dir structure is confusing - either we have api/extensions/v1alpha1 or just api/v1alpha1 .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Per your request, I removed the security group from the Request Authentication design. I'll add this to the community meeting agenda to get input from other maintainers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xref #809 to make a decision on API type grouping. IMO a separate PR should be submitted to resolve this issue.

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

var (
Expand All @@ -28,9 +29,14 @@ func init() {
if err := clientgoscheme.AddToScheme(scheme); err != nil {
panic(err)
}
if err := v1alpha1.AddToScheme(scheme); err != nil {
// Add Envoy Gateway types.
if err := egcfgv1a1.AddToScheme(scheme); err != nil {
panic(err)
}
if err := egv1a1.AddToScheme(scheme); err != nil {
panic(err)
}
// Add Gateway API types.
if err := gwapiv1b1.AddToScheme(scheme); err != nil {
panic(err)
}
Expand Down
30 changes: 30 additions & 0 deletions internal/gatewayapi/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
package gatewayapi

import (
"errors"
"fmt"
"strings"

"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/apis/v1beta1"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

const (
Expand Down Expand Up @@ -246,3 +250,29 @@ func layer4Protocol(protocolPort *ProtocolPort) string {
return UDPProtocol
}
}

// ValidateHTTPRouteFilter validates the provided filter.
func ValidateHTTPRouteFilter(filter *v1beta1.HTTPRouteFilter) error {
switch {
case filter == nil:
return errors.New("filter is nil")
case filter.Type == v1beta1.HTTPRouteFilterRequestMirror ||
filter.Type == v1beta1.HTTPRouteFilterURLRewrite ||
filter.Type == v1beta1.HTTPRouteFilterRequestRedirect ||
filter.Type == v1beta1.HTTPRouteFilterRequestHeaderModifier:
return nil
case filter.Type == v1beta1.HTTPRouteFilterExtensionRef:
switch {
case filter.ExtensionRef == nil:
return errors.New("extensionRef field must be specified for an extended filter")
case string(filter.ExtensionRef.Group) != egv1a1.GroupVersion.Group:
return fmt.Errorf("invalid group; must be %s", egv1a1.GroupVersion.Group)
case string(filter.ExtensionRef.Kind) != egv1a1.AuthenticationFilterKind:
return fmt.Errorf("invalid kind; must be %s", egv1a1.AuthenticationFilterKind)
default:
return nil
}
}

return fmt.Errorf("unsupported filter type: %v", filter.Type)
}
125 changes: 125 additions & 0 deletions internal/gatewayapi/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

// This file contains code derived from Contour,
// https://github.com/projectcontour/contour
// and is provided here subject to the following:
// Copyright Project Contour Authors
// SPDX-License-Identifier: Apache-2.0

package gatewayapi

import (
"testing"

"github.com/stretchr/testify/require"
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

func TestValidateAuthenFilterRef(t *testing.T) {
testCases := []struct {
name string
filter *gwapiv1b1.HTTPRouteFilter
expected bool
}{
{
name: "request mirror filter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterRequestMirror,
},
expected: true,
},
{
name: "url rewrite filter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterURLRewrite,
},
expected: true,
},
{
name: "request header modifier filter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterRequestHeaderModifier,
},
expected: true,
},
{
name: "request redirect filter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterRequestRedirect,
},
expected: true,
},
{
name: "unsupported extended filter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterExtensionRef,
ExtensionRef: &gwapiv1b1.LocalObjectReference{
Group: "UnsupportedGroup",
Kind: "UnsupportedKind",
Name: "test",
},
},
expected: false,
},
{
name: "extended filter with missing reference",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterExtensionRef,
},
expected: false,
},
{
name: "invalid authenticationfilter group",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterExtensionRef,
ExtensionRef: &gwapiv1b1.LocalObjectReference{
Group: "UnsupportedGroup",
Kind: egv1a1.AuthenticationFilterKind,
Name: "test",
},
},
expected: false,
},
{
name: "invalid authenticationfilter kind",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterExtensionRef,
ExtensionRef: &gwapiv1b1.LocalObjectReference{
Group: gwapiv1b1.Group(egv1a1.GroupVersion.Group),
Kind: "UnsupportedKind",
Name: "test",
},
},
expected: false,
},
{
name: "valid authenticationfilter",
filter: &gwapiv1b1.HTTPRouteFilter{
Type: gwapiv1b1.HTTPRouteFilterExtensionRef,
ExtensionRef: &gwapiv1b1.LocalObjectReference{
Group: gwapiv1b1.Group(egv1a1.GroupVersion.Group),
Kind: egv1a1.AuthenticationFilterKind,
Name: "test",
},
},
expected: true,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
err := ValidateHTTPRouteFilter(tc.filter)
if tc.expected {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}
15 changes: 15 additions & 0 deletions internal/gatewayapi/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/apis/v1beta1"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/ir"
)

Expand Down Expand Up @@ -58,6 +59,20 @@ type Resources struct {
Namespaces []*v1.Namespace
Services []*v1.Service
Secrets []*v1.Secret
AuthenFilters []*egv1a1.AuthenticationFilter
}

func NewResources() *Resources {
return &Resources{
Gateways: []*v1beta1.Gateway{},
HTTPRoutes: []*v1beta1.HTTPRoute{},
TLSRoutes: []*v1alpha2.TLSRoute{},
Services: []*v1.Service{},
Secrets: []*v1.Secret{},
ReferenceGrants: []*v1alpha2.ReferenceGrant{},
Namespaces: []*v1.Namespace{},
AuthenFilters: []*egv1a1.AuthenticationFilter{},
}
}

func (r *Resources) GetNamespace(name string) *v1.Namespace {
Expand Down
12 changes: 12 additions & 0 deletions internal/gatewayapi/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# It should be run by config/default
resources:
- bases/config.gateway.envoyproxy.io_envoyproxies.yaml
- bases/gateway.envoyproxy.io_authenticationfilters.yaml
#+kubebuilder:scaffold:crdkustomizeresource

patchesStrategicMerge:
Expand Down
9 changes: 9 additions & 0 deletions internal/provider/kubernetes/config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ rules:
- get
- list
- watch
- apiGroups:
- gateway.envoyproxy.io
resources:
- authenticationfilters
verbs:
- get
- list
- update
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
Expand Down
Loading