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

implement global cors configuration #2306

Merged
merged 2 commits into from
Apr 8, 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
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,
tharindu1st marked this conversation as resolved.
Show resolved Hide resolved
AccessControlAllowOrigins: []string{"*"},
AccessControlAllowMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"},
AccessControlAllowHeaders: []string{"authorization", "Access-Control-Allow-Origin", "Content-Type", "Internal-key"},
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
4 changes: 2 additions & 2 deletions adapter/internal/operator/controllers/dp/api_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1070,8 +1070,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 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) 2024, 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
Loading