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

Subscription ratelimit #2443

Merged
merged 11 commits into from
Sep 9, 2024
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
2 changes: 1 addition & 1 deletion adapter/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/wso2/apk/common-go-libs v0.0.0-20231208100153-24bee7b4bd81
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.33.0
google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
Expand Down
4 changes: 2 additions & 2 deletions adapter/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
155 changes: 153 additions & 2 deletions adapter/internal/oasparser/envoyconf/routes_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
extAuthService "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
envoy_type_matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
metadatav3 "github.com/envoyproxy/go-control-plane/envoy/type/metadata/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
"github.com/golang/protobuf/ptypes/any"
logger "github.com/wso2/apk/adapter/internal/loggers"
Expand All @@ -41,6 +42,21 @@ import (
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

// Constants for Rate Limiting
const (
DescriptorKeyForSubscription = "subscription"
DescriptorKeyForPolicy = "policy"
DescriptorKeyForOrganization = "organization"
extAuthzFilterName = "envoy.filters.http.ext_authz"

descriptorMetadataKeyForSubscription = "ratelimit:subscription"
descriptorMetadataKeyForUsagePolicy = "ratelimit:usage-policy"
descriptorMetadataKeyForOrganization = "ratelimit:organization"
descriptorMetadataKeyForBurstCtrlSubscription = "burstCtrl:subscription"
descriptorMetadataKeyForBurstCtrlUsagePolicy = "burstCtrl:usage-policy"
descriptorMetadataKeyForBurstCtrlOrganization = "burstCtrl:organization"
)

func generateRouteConfig(routeName string, match *routev3.RouteMatch, action *routev3.Route_Route, redirectAction *routev3.Route_Redirect,
metadata *corev3.Metadata, decorator *routev3.Decorator, typedPerFilterConfig map[string]*anypb.Any,
requestHeadersToAdd []*corev3.HeaderValueOption, requestHeadersToRemove []string,
Expand Down Expand Up @@ -168,7 +184,6 @@ func mapStatusCodeToEnum(statusCode int) int {
}

func generateRateLimitPolicy(ratelimitCriteria *ratelimitCriteria) []*routev3.RateLimit {

environmentValue := ratelimitCriteria.environment
if ratelimitCriteria.level != RateLimitPolicyAPILevel && ratelimitCriteria.envType == opConstants.Sandbox {
environmentValue += "_sandbox"
Expand Down Expand Up @@ -223,7 +238,10 @@ func generateRateLimitPolicy(ratelimitCriteria *ratelimitCriteria) []*routev3.Ra
},
})
}
return []*routev3.RateLimit{&rateLimit}

ratelimits := []*routev3.RateLimit{&rateLimit}
ratelimits = addSubscriptionRatelimitActions(ratelimits)
return ratelimits
}

func generateHTTPMethodMatcher(methodRegex string, sandClusterName string) []*routev3.HeaderMatcher {
Expand Down Expand Up @@ -263,6 +281,139 @@ func generateHeaderMatcher(headerName, valueRegex string) *routev3.HeaderMatcher
return headerMatcherArray
}

func addSubscriptionRatelimitActions(actions []*routev3.RateLimit) []*routev3.RateLimit {
return append(actions,
&routev3.RateLimit{
Actions: []*routev3.RateLimit_Action{
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForOrganization,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForOrganization,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForSubscription,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForSubscription,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForPolicy,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForUsagePolicy,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
},
}, &routev3.RateLimit{
Actions: []*routev3.RateLimit_Action{
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForOrganization,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForOrganization,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForSubscription,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForSubscription,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
{
ActionSpecifier: &routev3.RateLimit_Action_Metadata{
Metadata: &routev3.RateLimit_Action_MetaData{
DescriptorKey: DescriptorKeyForPolicy,
MetadataKey: &metadatav3.MetadataKey{
Key: extAuthzFilterName,
Path: []*metadatav3.MetadataKey_PathSegment{
{
Segment: &metadatav3.MetadataKey_PathSegment_Key{
Key: descriptorMetadataKeyForUsagePolicy,
},
},
},
},
Source: routev3.RateLimit_Action_MetaData_DYNAMIC,
SkipIfAbsent: true,
},
},
},
{
ActionSpecifier: &routev3.RateLimit_Action_GenericKey_{
GenericKey: &routev3.RateLimit_Action_GenericKey{
DescriptorKey: "burst",
DescriptorValue: "enabled",
},
},
},
},
})
}

func generateRegexMatchAndSubstitute(routePath, endpointResourcePath string,
pathMatchType gwapiv1.PathMatchType) *envoy_type_matcherv3.RegexMatchAndSubstitute {
substitutionString := generateSubstitutionString(endpointResourcePath, pathMatchType)
Expand Down
5 changes: 3 additions & 2 deletions adapter/internal/oasparser/model/adapter_internal_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/wso2/apk/adapter/internal/operator/utils"
dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1"
dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2"
dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3"
"golang.org/x/exp/maps"
"k8s.io/apimachinery/pkg/types"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
Expand Down Expand Up @@ -463,7 +464,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoHTTPRouteCR(httpRoute *gwap
if outputAPIPolicy != nil {
apiPolicy = *outputAPIPolicy
}
var ratelimitPolicy *dpv1alpha1.RateLimitPolicy
var ratelimitPolicy *dpv1alpha3.RateLimitPolicy
if outputRatelimitPolicy != nil {
ratelimitPolicy = *outputRatelimitPolicy
}
Expand Down Expand Up @@ -946,7 +947,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoGQLRouteCR(gqlRoute *dpv1al
if outputAPIPolicy != nil {
apiPolicy = *outputAPIPolicy
}
var ratelimitPolicy *dpv1alpha1.RateLimitPolicy
var ratelimitPolicy *dpv1alpha3.RateLimitPolicy
if outputRatelimitPolicy != nil {
ratelimitPolicy = *outputRatelimitPolicy
}
Expand Down
6 changes: 4 additions & 2 deletions adapter/internal/oasparser/model/custom_ratelimit_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

package model

import dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1"
import (
dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3"
)

// RateLimit is the rate limit values for a policy
type RateLimit struct {
Expand All @@ -39,7 +41,7 @@ type CustomRateLimitPolicy struct {
}

// ParseCustomRateLimitPolicy parses the custom rate limit policy
func ParseCustomRateLimitPolicy(customRateLimitCR dpv1alpha1.RateLimitPolicy) *CustomRateLimitPolicy {
func ParseCustomRateLimitPolicy(customRateLimitCR dpv1alpha3.RateLimitPolicy) *CustomRateLimitPolicy {
rlPolicy := concatRateLimitPolicies(&customRateLimitCR, nil)
return &CustomRateLimitPolicy{
Key: rlPolicy.Spec.Override.Custom.Key,
Expand Down
11 changes: 6 additions & 5 deletions adapter/internal/oasparser/model/http_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/wso2/apk/adapter/internal/operator/utils"
dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1"
dpv1alpha2 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2"
dpv1alpha3 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha3"
"k8s.io/apimachinery/pkg/types"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)
Expand All @@ -38,8 +39,8 @@ type ResourceParams struct {
BackendJWTMapping map[string]dpv1alpha1.BackendJWT
BackendMapping map[string]*dpv1alpha2.ResolvedBackend
ResourceScopes map[string]dpv1alpha1.Scope
RateLimitPolicies map[string]dpv1alpha1.RateLimitPolicy
ResourceRateLimitPolicies map[string]dpv1alpha1.RateLimitPolicy
RateLimitPolicies map[string]dpv1alpha3.RateLimitPolicy
ResourceRateLimitPolicies map[string]dpv1alpha3.RateLimitPolicy
}

func parseBackendJWTTokenToInternal(backendJWTToken dpv1alpha1.BackendJWTSpec) *BackendJWTTokenInfo {
Expand Down Expand Up @@ -96,7 +97,7 @@ func getCorsConfigFromAPIPolicy(apiPolicy *dpv1alpha2.APIPolicy) *CorsConfig {
return &corsConfig
}

func parseRateLimitPolicyToInternal(ratelimitPolicy *dpv1alpha1.RateLimitPolicy) *RateLimitPolicy {
func parseRateLimitPolicyToInternal(ratelimitPolicy *dpv1alpha3.RateLimitPolicy) *RateLimitPolicy {
var rateLimitPolicyInternal *RateLimitPolicy
if ratelimitPolicy != nil && ratelimitPolicy.Spec.Override != nil {
if ratelimitPolicy.Spec.Override.API.RequestsPerUnit > 0 {
Expand Down Expand Up @@ -191,8 +192,8 @@ func GetBackendBasePath(backendName types.NamespacedName, backendMapping map[str
return ""
}

func concatRateLimitPolicies(schemeUp *dpv1alpha1.RateLimitPolicy, schemeDown *dpv1alpha1.RateLimitPolicy) *dpv1alpha1.RateLimitPolicy {
finalRateLimit := dpv1alpha1.RateLimitPolicy{}
func concatRateLimitPolicies(schemeUp *dpv1alpha3.RateLimitPolicy, schemeDown *dpv1alpha3.RateLimitPolicy) *dpv1alpha3.RateLimitPolicy {
finalRateLimit := dpv1alpha3.RateLimitPolicy{}
if schemeUp != nil && schemeDown != nil {
finalRateLimit.Spec.Override = utils.SelectPolicy(&schemeUp.Spec.Override, &schemeUp.Spec.Default, &schemeDown.Spec.Override, &schemeDown.Spec.Default)
} else if schemeUp != nil {
Expand Down
Loading
Loading