Skip to content

Commit

Permalink
implement global cors configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
tharindu1st committed Apr 8, 2024
1 parent 77948bb commit 5200462
Show file tree
Hide file tree
Showing 51 changed files with 609 additions and 290 deletions.
9 changes: 9 additions & 0 deletions adapter/config/default_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ var defaultConfig = &Config{
EnableOutboundCertificateHeader: false,
},
},
Cors: cors{
Enabled: true,
AccessControlAllowOrigins: []string{"*"},
AccessControlAllowMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"},
AccessControlAllowHeaders: []string{"authorization", "Access-Control-Allow-Origin", "Content-Type"},
AccessControlAllowCredentials: false,
AccessControlExposeHeaders: []string{"*"},
},

AuthService: authService{
Port: 8081,
MaxMessageSize: 1000000000,
Expand Down
12 changes: 12 additions & 0 deletions adapter/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ type enforcer struct {
MandateSubscriptionValidation bool
MandateInternalKeyValidation bool
Client httpClient
Cors cors
}

// Cors represents the configurations related to Cross-Origin Resource Sharing
type cors struct {
Enabled bool
AccessControlAllowOrigins []string
AccessControlAllowMethods []string
AccessControlAllowHeaders []string
AccessControlMaxAge *int
AccessControlAllowCredentials bool
AccessControlExposeHeaders []string
}

// Router to enforcer request body passing configurations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func CreateRoutesWithClusters(adapterInternalAPI *model.AdapterInternalAPI, inte

corsConfig := adapterInternalAPI.GetCorsConfig()
var methods []string
if corsConfig != nil {
if corsConfig != nil && corsConfig.Enabled {
methods = append(methods, "GET", "OPTIONS")
} else {
methods = append(methods, "GET")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/wso2/apk/adapter/internal/dataholder"
"github.com/wso2/apk/adapter/internal/discovery/xds"
"github.com/wso2/apk/adapter/internal/loggers"
envoy "github.com/wso2/apk/adapter/internal/oasparser/envoyconf"
"github.com/wso2/apk/adapter/internal/operator/constants"
"github.com/wso2/apk/adapter/internal/operator/synchronizer"
Expand Down Expand Up @@ -131,7 +132,6 @@ func TestCreateRoutesWithClustersWithExactAndRegularExpressionRules(t *testing.T
httpRouteState.BackendMapping = backendMapping

apiState.ProdHTTPRoute = &httpRouteState

adapterInternalAPI, labels, err := synchronizer.UpdateInternalMapsFromHTTPRoute(apiState, &httpRouteState, constants.Production)
assert.Equal(t, map[string]struct{}{"default-gateway": {}}, labels, "Labels are incorrect.")
assert.Nil(t, err, "Error should not be present when apiState is converted to a AdapterInternalAPI object")
Expand Down Expand Up @@ -172,11 +172,14 @@ func TestCreateRoutesWithClustersWithExactAndRegularExpressionRules(t *testing.T
assert.Equal(t, uint32(7002), regexPathClusterPort, "Regex path cluster's assigned host is incorrect.")
assert.Equal(t, uint32(0), regexPathClusterPriority, "Regex path cluster's assigned priority is incorrect.")

assert.Equal(t, 3, len(routes), "Created number of routes are incorrect.")
assert.Contains(t, []string{"^/test-api/2\\.0\\.0/exact-path-api/2\\.0\\.0/\\(\\.\\*\\)/exact-path([/]{0,1})"}, routes[1].GetMatch().GetSafeRegex().Regex)
assert.Contains(t, []string{"^/test-api/2\\.0\\.0/regex-path/2.0.0/userId/([^/]+)/orderId/([^/]+)([/]{0,1})"}, routes[2].GetMatch().GetSafeRegex().Regex)
assert.NotEqual(t, routes[1].GetMatch().GetSafeRegex().Regex, routes[2].GetMatch().GetSafeRegex().Regex,
assert.Equal(t, 5, len(routes), "Created number of routes are incorrect.")
assert.Contains(t, []string{"^/test-api/2\\.0\\.0/exact-path-api/2\\.0\\.0/\\(\\.\\*\\)/exact-path([/]{0,1})"}, routes[2].GetMatch().GetSafeRegex().Regex)
assert.Contains(t, []string{"^/test-api/2\\.0\\.0/regex-path/2.0.0/userId/([^/]+)/orderId/([^/]+)([/]{0,1})"}, routes[3].GetMatch().GetSafeRegex().Regex)
assert.NotEqual(t, routes[2].GetMatch().GetSafeRegex().Regex, routes[3].GetMatch().GetSafeRegex().Regex,
"The route regex for the two paths should not be the same")
for _, route := range routes {
loggers.LoggerAPKOperator.Infof("routes ==" + route.GetMatch().GetSafeRegex().Regex)
}
}

func TestExtractAPIDetailsFromHTTPRouteForDefaultCase(t *testing.T) {
Expand Down
29 changes: 19 additions & 10 deletions adapter/internal/oasparser/model/http_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package model

import (
"github.com/google/uuid"
"github.com/wso2/apk/adapter/config"
"github.com/wso2/apk/adapter/internal/oasparser/constants"
"github.com/wso2/apk/adapter/internal/operator/utils"
dpv1alpha1 "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1"
Expand Down Expand Up @@ -68,23 +69,31 @@ func parseBackendJWTTokenToInternal(backendJWTToken dpv1alpha1.BackendJWTSpec) *
}

func getCorsConfigFromAPIPolicy(apiPolicy *dpv1alpha2.APIPolicy) *CorsConfig {
var corsConfig *CorsConfig
globalCorsConfig := config.ReadConfigs().Enforcer.Cors

var corsConfig = CorsConfig{
Enabled: globalCorsConfig.Enabled,
AccessControlAllowCredentials: globalCorsConfig.AccessControlAllowCredentials,
AccessControlAllowHeaders: globalCorsConfig.AccessControlAllowHeaders,
AccessControlAllowMethods: globalCorsConfig.AccessControlAllowMethods,
AccessControlAllowOrigins: globalCorsConfig.AccessControlAllowOrigins,
AccessControlExposeHeaders: globalCorsConfig.AccessControlExposeHeaders,
AccessControlMaxAge: globalCorsConfig.AccessControlMaxAge,
}
if apiPolicy != nil && apiPolicy.Spec.Override != nil {
if apiPolicy.Spec.Override.CORSPolicy != nil {
corsConfig = &CorsConfig{
Enabled: true,
AccessControlAllowCredentials: apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowCredentials,
AccessControlAllowHeaders: apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowHeaders,
AccessControlAllowMethods: apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowMethods,
AccessControlAllowOrigins: apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowOrigins,
AccessControlExposeHeaders: apiPolicy.Spec.Override.CORSPolicy.AccessControlExposeHeaders,
}
corsConfig.Enabled = apiPolicy.Spec.Override.CORSPolicy.Enabled
corsConfig.AccessControlAllowCredentials = apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowCredentials
corsConfig.AccessControlAllowHeaders = apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowHeaders
corsConfig.AccessControlAllowMethods = apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowMethods
corsConfig.AccessControlAllowOrigins = apiPolicy.Spec.Override.CORSPolicy.AccessControlAllowOrigins
corsConfig.AccessControlExposeHeaders = apiPolicy.Spec.Override.CORSPolicy.AccessControlExposeHeaders
if apiPolicy.Spec.Override.CORSPolicy.AccessControlMaxAge != nil {
corsConfig.AccessControlMaxAge = apiPolicy.Spec.Override.CORSPolicy.AccessControlMaxAge
}
}
}
return corsConfig
return &corsConfig
}

func parseRateLimitPolicyToInternal(ratelimitPolicy *dpv1alpha1.RateLimitPolicy) *RateLimitPolicy {
Expand Down
9 changes: 5 additions & 4 deletions adapter/internal/operator/controllers/dp/api_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ func isAPIPropagatable(apiState *synchronizer.APIState) bool {
return false
}
// Only valid organization's APIs can be propagated to CP
return utils.ContainsString(validOrgs, apiState.APIDefinition.Spec.Organization)
return utils.ContainsString(validOrgs, apiState.APIDefinition.Spec.Organization)
}

func (apiReconciler *APIReconciler) resolveGQLRouteRefs(ctx context.Context, gqlRouteRefs []string,
Expand Down Expand Up @@ -1061,8 +1061,8 @@ func (apiReconciler *APIReconciler) retriveParentAPIsAndUpdateOwnerReferene(ctx
}
requests = apiReconciler.getAPIsForInterceptorService(ctx, &interceptorService)
apiReconciler.handleOwnerReference(ctx, &interceptorService, &requests)
case *dpv1alpha1.APIPolicy:
var apiPolicy dpv1alpha1.APIPolicy
case *dpv1alpha2.APIPolicy:
var apiPolicy dpv1alpha2.APIPolicy
namesapcedName := types.NamespacedName{
Name: string(obj.GetName()),
Namespace: string(obj.GetNamespace()),
Expand All @@ -1072,6 +1072,7 @@ func (apiReconciler *APIReconciler) retriveParentAPIsAndUpdateOwnerReferene(ctx
return
}
requests = apiReconciler.getAPIsForAPIPolicy(ctx, &apiPolicy)
loggers.LoggerAPKOperator.Infof("API Policy requests %v", apiPolicy)
apiReconciler.handleOwnerReference(ctx, &apiPolicy, &requests)
case *dpv1alpha2.Authentication:
var auth dpv1alpha2.Authentication
Expand Down Expand Up @@ -1472,7 +1473,7 @@ func (apiReconciler *APIReconciler) getAPIsForBackend(ctx context.Context, obj k
loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", backend))
return []reconcile.Request{}
}

httpRouteList := &gwapiv1b1.HTTPRouteList{}
if err := apiReconciler.client.List(ctx, httpRouteList, &k8client.ListOptions{
FieldSelector: fields.OneTermEqualSelector(backendHTTPRouteIndex, utils.NamespacedName(backend).String()),
Expand Down
9 changes: 5 additions & 4 deletions common-go-libs/PROJECT
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Code generated by tool. DO NOT EDIT.
# This file is used to track the info used to scaffold your project
# and allow the plugins properly work.
# More info: https://book.kubebuilder.io/reference/project-config.html
domain: wso2.com
layout:
- go.kubebuilder.io/v3
Expand Down Expand Up @@ -46,6 +42,7 @@ resources:
path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1
version: v1alpha1
webhooks:
conversion: true
defaulting: true
validation: true
webhookVersion: v1
Expand Down Expand Up @@ -130,6 +127,10 @@ resources:
kind: APIPolicy
path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2
version: v1alpha2
webhooks:
conversion: true
defaulting: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
Expand Down
184 changes: 184 additions & 0 deletions common-go-libs/apis/dp/v1alpha1/apipolicy_conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* 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 v1alpha1

import (
"github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2"
"sigs.k8s.io/controller-runtime/pkg/conversion"
gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

// ConvertTo converts this API CR to the Hub version (v1alpha2).
// src is v1alpha1.API and dst is v1alpha2.API.
func (src *APIPolicy) ConvertTo(dstRaw conversion.Hub) error {

dst := dstRaw.(*v1alpha2.APIPolicy)
dst.ObjectMeta = src.ObjectMeta
if src.Spec.Default != nil {
var convertedSpec = v1alpha2.PolicySpec{}
if src.Spec.Default.BackendJWTPolicy != nil {
convertedSpec.BackendJWTPolicy = &v1alpha2.BackendJWTToken{
Name: src.Spec.Default.BackendJWTPolicy.Name}
}
if src.Spec.Default.CORSPolicy != nil {
convertedSpec.CORSPolicy = &v1alpha2.CORSPolicy{
Enabled: true,
AccessControlAllowCredentials: src.Spec.Default.CORSPolicy.AccessControlAllowCredentials,
AccessControlAllowHeaders: src.Spec.Default.CORSPolicy.AccessControlAllowHeaders,
AccessControlAllowMethods: src.Spec.Default.CORSPolicy.AccessControlAllowMethods,
AccessControlAllowOrigins: src.Spec.Default.CORSPolicy.AccessControlAllowOrigins,
AccessControlExposeHeaders: src.Spec.Default.CORSPolicy.AccessControlExposeHeaders,
AccessControlMaxAge: src.Spec.Default.CORSPolicy.AccessControlMaxAge}
}
if src.Spec.Default.RequestInterceptors != nil {
convertedSpec.RequestInterceptors = []v1alpha2.InterceptorReference{}
for _, interceptor := range src.Spec.Default.RequestInterceptors {
convertedSpec.RequestInterceptors = append(convertedSpec.RequestInterceptors, v1alpha2.InterceptorReference{
Name: interceptor.Name})
}
}
if src.Spec.Default.ResponseInterceptors != nil {
convertedSpec.ResponseInterceptors = []v1alpha2.InterceptorReference{}
for _, interceptor := range src.Spec.Default.ResponseInterceptors {
convertedSpec.ResponseInterceptors = append(convertedSpec.ResponseInterceptors, v1alpha2.InterceptorReference{
Name: interceptor.Name})
}
}
convertedSpec.SubscriptionValidation = false
dst.Spec.Default = &convertedSpec
}

if src.Spec.Override != nil {
var convertedSpec = v1alpha2.PolicySpec{}
if src.Spec.Override.BackendJWTPolicy != nil {
convertedSpec.BackendJWTPolicy = &v1alpha2.BackendJWTToken{
Name: src.Spec.Override.BackendJWTPolicy.Name}
}
if src.Spec.Override.CORSPolicy != nil {
convertedSpec.CORSPolicy = &v1alpha2.CORSPolicy{
Enabled: true,
AccessControlAllowCredentials: src.Spec.Override.CORSPolicy.AccessControlAllowCredentials,
AccessControlAllowHeaders: src.Spec.Override.CORSPolicy.AccessControlAllowHeaders,
AccessControlAllowMethods: src.Spec.Override.CORSPolicy.AccessControlAllowMethods,
AccessControlAllowOrigins: src.Spec.Override.CORSPolicy.AccessControlAllowOrigins,
AccessControlExposeHeaders: src.Spec.Override.CORSPolicy.AccessControlExposeHeaders,
AccessControlMaxAge: src.Spec.Override.CORSPolicy.AccessControlMaxAge}
}
if src.Spec.Override.RequestInterceptors != nil {
convertedSpec.RequestInterceptors = []v1alpha2.InterceptorReference{}
for _, interceptor := range src.Spec.Override.RequestInterceptors {
convertedSpec.RequestInterceptors = append(convertedSpec.RequestInterceptors, v1alpha2.InterceptorReference{
Name: interceptor.Name})
}
}
if src.Spec.Override.ResponseInterceptors != nil {
convertedSpec.ResponseInterceptors = []v1alpha2.InterceptorReference{}
for _, interceptor := range src.Spec.Override.ResponseInterceptors {
convertedSpec.ResponseInterceptors = append(convertedSpec.ResponseInterceptors, v1alpha2.InterceptorReference{
Name: interceptor.Name})
}
}
convertedSpec.SubscriptionValidation = false
dst.Spec.Override = &convertedSpec
}
if src.Spec.TargetRef.Name != "" {
dst.Spec.TargetRef = gwapiv1b1.PolicyTargetReference{
Name: src.Spec.TargetRef.Name,
Group: src.Spec.TargetRef.Group,
Kind: src.Spec.TargetRef.Kind}
}
return nil
}

// ConvertFrom converts from the Hub version (v1alpha2) to this version.
// src is v1alpha1.API and dst is v1alpha2.API.
func (src *APIPolicy) ConvertFrom(srcRaw conversion.Hub) error {

dst := srcRaw.(*v1alpha2.APIPolicy)
src.ObjectMeta = dst.ObjectMeta
// Spec
if dst.Spec.Default != nil {
var convertedSpec = PolicySpec{}
if dst.Spec.Default.BackendJWTPolicy != nil {
convertedSpec.BackendJWTPolicy = &BackendJWTToken{
Name: dst.Spec.Default.BackendJWTPolicy.Name}
}
if dst.Spec.Default.CORSPolicy != nil {
convertedSpec.CORSPolicy = &CORSPolicy{
AccessControlAllowCredentials: dst.Spec.Default.CORSPolicy.AccessControlAllowCredentials,
AccessControlAllowHeaders: dst.Spec.Default.CORSPolicy.AccessControlAllowHeaders,
AccessControlAllowMethods: dst.Spec.Default.CORSPolicy.AccessControlAllowMethods,
AccessControlAllowOrigins: dst.Spec.Default.CORSPolicy.AccessControlAllowOrigins,
AccessControlExposeHeaders: dst.Spec.Default.CORSPolicy.AccessControlExposeHeaders,
AccessControlMaxAge: dst.Spec.Default.CORSPolicy.AccessControlMaxAge}
}
if dst.Spec.Default.RequestInterceptors != nil {
convertedSpec.RequestInterceptors = []InterceptorReference{}
for _, interceptor := range dst.Spec.Default.RequestInterceptors {
convertedSpec.RequestInterceptors = append(convertedSpec.RequestInterceptors, InterceptorReference{
Name: interceptor.Name})
}
}
if dst.Spec.Default.ResponseInterceptors != nil {
convertedSpec.ResponseInterceptors = []InterceptorReference{}
for _, interceptor := range dst.Spec.Default.ResponseInterceptors {
convertedSpec.ResponseInterceptors = append(convertedSpec.ResponseInterceptors, InterceptorReference{
Name: interceptor.Name})
}
}
src.Spec.Default = &convertedSpec
}
if dst.Spec.Override != nil {
var convertedSpec = PolicySpec{}
if dst.Spec.Override.BackendJWTPolicy != nil {
convertedSpec.BackendJWTPolicy = &BackendJWTToken{
Name: dst.Spec.Override.BackendJWTPolicy.Name}
}
if dst.Spec.Override.CORSPolicy != nil {
convertedSpec.CORSPolicy = &CORSPolicy{
AccessControlAllowCredentials: dst.Spec.Override.CORSPolicy.AccessControlAllowCredentials,
AccessControlAllowHeaders: dst.Spec.Override.CORSPolicy.AccessControlAllowHeaders,
AccessControlAllowMethods: dst.Spec.Override.CORSPolicy.AccessControlAllowMethods,
AccessControlAllowOrigins: dst.Spec.Override.CORSPolicy.AccessControlAllowOrigins,
AccessControlExposeHeaders: dst.Spec.Override.CORSPolicy.AccessControlExposeHeaders,
AccessControlMaxAge: dst.Spec.Override.CORSPolicy.AccessControlMaxAge}
}
if dst.Spec.Override.RequestInterceptors != nil {
convertedSpec.RequestInterceptors = []InterceptorReference{}
for _, interceptor := range dst.Spec.Override.RequestInterceptors {
convertedSpec.RequestInterceptors = append(convertedSpec.RequestInterceptors, InterceptorReference{
Name: interceptor.Name})
}
}
if dst.Spec.Override.ResponseInterceptors != nil {
convertedSpec.ResponseInterceptors = []InterceptorReference{}
for _, interceptor := range dst.Spec.Override.ResponseInterceptors {
convertedSpec.ResponseInterceptors = append(convertedSpec.ResponseInterceptors, InterceptorReference{
Name: interceptor.Name})
}
}
src.Spec.Override = &convertedSpec
}
if dst.Spec.TargetRef.Name != "" {
src.Spec.TargetRef = gwapiv1b1.PolicyTargetReference{
Name: dst.Spec.TargetRef.Name,
Group: dst.Spec.TargetRef.Group,
Kind: dst.Spec.TargetRef.Kind}
}
return nil
}
Loading

0 comments on commit 5200462

Please sign in to comment.