Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
76 changes: 76 additions & 0 deletions api/applyconfiguration/api/v1alpha1/corspolicy.go

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

9 changes: 9 additions & 0 deletions api/applyconfiguration/api/v1alpha1/trafficpolicyspec.go

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

38 changes: 38 additions & 0 deletions api/applyconfiguration/internal/internal.go

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

2 changes: 2 additions & 0 deletions api/applyconfiguration/utils.go

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

31 changes: 31 additions & 0 deletions api/v1alpha1/traffic_policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ type TrafficPolicySpec struct {
// This controls the rate at which requests are allowed to be processed.
// +optional
RateLimit *RateLimit `json:"rateLimit,omitempty"`

// Cors specifies the CORS configuration for the policy.
// +optional
Cors *CorsPolicy `json:"cors,omitempty"`
}

// TransformationPolicy config is used to modify envoy behavior at a route level.
Expand Down Expand Up @@ -333,3 +337,30 @@ type RateLimitDescriptorEntryGeneric struct {
// +required
Value string `json:"value"`
}

// CorsPolicy configures CORS settings.
type CorsPolicy struct {
// An origin is allowed if any of the strings match
// +optional
AllowOrigins []string `json:"allowOrigins"`

// Specifies the content for the access-control-allow-methods header
// +optional
AllowMethods []string `json:"allowMethods"`

// Specifies the content for the access-control-allow-headers header
// +optional
AllowHeaders []string `json:"allowHeaders"`

// Specifies the content for the access-control-allow-credentials header
// +optional
AllowCredentials bool `json:"allowCredentials"`

// Specifies the content for the access-control-expose-headers header
// +optional
ExposeHeaders []string `json:"exposeHeaders"`

// Specifies the content for the access-control-max-age header
// +optional
MaxAge string `json:"maxAge"`
}
40 changes: 40 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/protobuf v1.5.4
github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect
github.com/golangci/go-printf-func-name v0.1.0 // indirect
github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect
Expand Down
1 change: 1 addition & 0 deletions hack/utils/oss_compliance/osa_provided.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Name|Version|License
[ghodss/yaml](https://github.com/ghodss/yaml)|v1.0.1-0.20190212211648-25d852aebe32|MIT License
[go-logr/logr](https://github.com/go-logr/logr)|v1.4.2|Apache License 2.0
[go-logr/zapr](https://github.com/go-logr/zapr)|v1.3.0|Apache License 2.0
[golang/protobuf](https://github.com/golang/protobuf)|v1.5.4|BSD 3-clause "New" or "Revised" License
[google/go-cmp](https://github.com/google/go-cmp)|v0.7.0|BSD 3-clause "New" or "Revised" License
[grpc-ecosystem/go-grpc-middleware](https://github.com/grpc-ecosystem/go-grpc-middleware)|v1.4.0|Apache License 2.0
[kelseyhightower/envconfig](https://github.com/kelseyhightower/envconfig)|v1.4.0|MIT License
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,29 @@ spec:
- CHAT_STREAMING
type: string
type: object
cors:
properties:
allowCredentials:
type: boolean
allowHeaders:
items:
type: string
type: array
allowMethods:
items:
type: string
type: array
allowOrigins:
items:
type: string
type: array
exposeHeaders:
items:
type: string
type: array
maxAge:
type: string
type: object
extAuth:
properties:
contextExtensions:
Expand Down
91 changes: 91 additions & 0 deletions internal/kgateway/extensions2/plugins/trafficpolicy/cors_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package trafficpolicy

import (
"strings"

corsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/cors/v3"
matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
"github.com/golang/protobuf/ptypes/wrappers"
"google.golang.org/protobuf/proto"

"github.com/kgateway-dev/kgateway/v2/api/v1alpha1"
)

type CorsIR struct {
// corsConfig is the envoy cors policy
corsConfig *corsv3.CorsPolicy
}

func (c *CorsIR) Equals(other *CorsIR) bool {
if c == nil && other == nil {
return true
}
if c == nil || other == nil {
return false
}

return proto.Equal(c.corsConfig, other.corsConfig)
}

// corsForSpec translates the cors spec into an envoy cors policy and stores it in the traffic policy IR
func corsForSpec(spec v1alpha1.TrafficPolicySpec, out *trafficPolicySpecIr) error {
if spec.Cors == nil {
return nil
}
corsConfig, err := toCorsFilterConfig(spec.Cors)
if err != nil {
return err
}
out.cors = &CorsIR{
corsConfig: corsConfig,
}
return nil
}

func toCorsFilterConfig(t *v1alpha1.CorsPolicy) (*corsv3.CorsPolicy, error) {
if t == nil {
return nil, nil
}

/*
Envoy CORS configuration example:

allow_origin_string_match:
- exact: "https://example.com"
allow_methods: "GET, POST, OPTIONS"
allow_headers: "Content-Type, Authorization"
max_age: "86400"
expose_headers: "X-Custom-Header"
allow_credentials: true
*/

corsPolicy := &corsv3.CorsPolicy{}
if len(t.AllowOrigins) > 0 {
origins := make([]*matcherv3.StringMatcher, len(t.AllowOrigins))
for i, origin := range t.AllowOrigins {
origins[i] = &matcherv3.StringMatcher{
MatchPattern: &matcherv3.StringMatcher_Exact{
Exact: origin,
},
}
}
corsPolicy.AllowOriginStringMatch = origins
}
if len(t.AllowMethods) > 0 {
corsPolicy.AllowMethods = strings.Join(t.AllowMethods, ", ")
}
if len(t.AllowHeaders) > 0 {
corsPolicy.AllowHeaders = strings.Join(t.AllowHeaders, ", ")
}
if t.AllowCredentials {
corsPolicy.AllowCredentials = &wrappers.BoolValue{Value: t.AllowCredentials}
}
if len(t.ExposeHeaders) > 0 {
corsPolicy.ExposeHeaders = strings.Join(t.ExposeHeaders, ", ")
}
if t.MaxAge != "" {
corsPolicy.MaxAge = t.MaxAge
}

return corsPolicy, nil
}
Loading
Loading