From 97b2ca22e35ea77ac27172d88fc9a096e4db6bdf Mon Sep 17 00:00:00 2001 From: sgayangi Date: Thu, 23 Nov 2023 11:20:46 +0530 Subject: [PATCH 01/15] Add: MTLS field in Auth CR --- .../apis/dp/v1alpha1/authentication_types.go | 21 ++++ .../crds/dp.wso2.com_authentications.yaml | 98 +++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go index 55da2c21b..2ab575fbe 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go @@ -38,6 +38,11 @@ type AuthSpec struct { // AuthTypes is to specify the authentication scheme types and details AuthTypes *APIAuth `json:"authTypes,omitempty"` + + // MutualSSL is to specify the features and certificates for mutual SSL + // + // +optional + MutualSSL *MutualSSLConfig `json:"mutualSSL,omitempty"` } // APIAuth Authentication scheme type and details @@ -59,6 +64,22 @@ type APIAuth struct { TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"` } +// MutualSSLConfig scheme type and details +type MutualSSLConfig struct { + // Required indicates whether mutualSSL is mandatory or optional + // +kubebuilder:validation:Enum=mandatory;optional + Required string `json:"required"` + + // CertificateInline is the Inline Certificate entry + CertificateInline *string `json:"certificateInline,omitempty"` + + // SecretRef denotes the reference to the Secret that contains the Certificate + SecretRef *RefConfig `json:"secretRef,omitempty"` + + // ConfigMapRef denotes the reference to the ConfigMap that contains the Certificate + ConfigMapRef *RefConfig `json:"configMapRef,omitempty"` +} + // TestConsoleKeyAuth Test Console Key Authentication scheme details type TestConsoleKeyAuth struct { // Header is the header name used to pass the Test Console Key diff --git a/helm-charts/crds/dp.wso2.com_authentications.yaml b/helm-charts/crds/dp.wso2.com_authentications.yaml index 3a289dcb2..fdced4d55 100644 --- a/helm-charts/crds/dp.wso2.com_authentications.yaml +++ b/helm-charts/crds/dp.wso2.com_authentications.yaml @@ -105,6 +105,55 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean + mutualSSL: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificateInline: + description: CertificateInline is the Inline Certificate entry + type: string + configMapRef: + description: ConfigMapRef denotes the reference to the ConfigMap + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRef: + description: SecretRef denotes the reference to the Secret + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + - required + type: object type: object override: description: AuthSpec specification of the authentication service @@ -176,6 +225,55 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean + mutualSSL: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificateInline: + description: CertificateInline is the Inline Certificate entry + type: string + configMapRef: + description: ConfigMapRef denotes the reference to the ConfigMap + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRef: + description: SecretRef denotes the reference to the Secret + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + - required + type: object type: object targetRef: description: PolicyTargetReference identifies an API object to apply From 81c84f3f6cd8bb77c218fc33cf81fd818da058c8 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Thu, 23 Nov 2023 11:24:54 +0530 Subject: [PATCH 02/15] Add: Internal adapter changes for MTLS support --- .../internal/oasparser/config_generator.go | 2 +- .../oasparser/model/adapter_internal_api.go | 26 ++-- .../bases/dp.wso2.com_authentications.yaml | 98 ++++++++++++++ .../operator/controllers/dp/api_controller.go | 127 +++++++++++++++--- .../operator/synchronizer/api_state.go | 1 + .../operator/synchronizer/rest_api.go | 4 + .../synchronizer/zz_generated.deepcopy.go | 5 + adapter/internal/operator/utils/utils.go | 25 ++++ common-go-libs/apis/dp/v1alpha1/mutualSSL.go | 24 ++++ .../apis/dp/v1alpha1/zz_generated.deepcopy.go | 55 ++++++++ 10 files changed, 338 insertions(+), 29 deletions(-) create mode 100644 common-go-libs/apis/dp/v1alpha1/mutualSSL.go diff --git a/adapter/internal/oasparser/config_generator.go b/adapter/internal/oasparser/config_generator.go index 0b09afb9d..fd8099ddb 100644 --- a/adapter/internal/oasparser/config_generator.go +++ b/adapter/internal/oasparser/config_generator.go @@ -215,7 +215,7 @@ func GetEnforcerAPI(adapterInternalAPI model.AdapterInternalAPI, vhost string) * EndpointSecurity: generateRPCEndpointSecurity(adapterInternalAPI.EndpointSecurity), // IsMockedApi: isMockedAPI, ClientCertificates: clientCertificates, - MutualSSL: adapterInternalAPI.GetXWSO2MutualSSL(), + MutualSSL: adapterInternalAPI.GetMutualSSL(), ApplicationSecurity: adapterInternalAPI.GetXWSO2ApplicationSecurity(), // GraphQLSchema: adapterInternalAPI.GraphQLSchema, // GraphqlComplexityInfo: adapterInternalAPI.GraphQLComplexities.Data.List, diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go index 01807d77a..b6165a471 100644 --- a/adapter/internal/oasparser/model/adapter_internal_api.go +++ b/adapter/internal/oasparser/model/adapter_internal_api.go @@ -65,7 +65,7 @@ type AdapterInternalAPI struct { xWso2RequestBodyPass bool IsDefaultVersion bool clientCertificates []Certificate - xWso2MutualSSL string + mutualSSL string xWso2ApplicationSecurity bool EnvType string backendJWTTokenInfo *BackendJWTTokenInfo @@ -335,8 +335,16 @@ func (adapterInternalAPI *AdapterInternalAPI) GetClientCerts() []Certificate { } // SetClientCerts set the client certificates of the API -func (adapterInternalAPI *AdapterInternalAPI) SetClientCerts(certs []Certificate) { - adapterInternalAPI.clientCertificates = certs +func (swagger *AdapterInternalAPI) SetClientCerts(apiName string, certs []string) { + var clientCerts []Certificate + for i, cert := range certs { + clientCert := Certificate{ + Alias: apiName + "-cert-" + strconv.Itoa(i), + Content: []byte(cert), + } + clientCerts = append(clientCerts, clientCert) + } + swagger.clientCertificates = clientCerts } // SetID set the Id of the API @@ -386,14 +394,14 @@ func (adapterInternalAPI *AdapterInternalAPI) GetXWSO2AuthHeader() string { return adapterInternalAPI.xWso2AuthHeader } -// SetXWSO2MutualSSL sets the optional or mandatory mTLS -func (adapterInternalAPI *AdapterInternalAPI) SetXWSO2MutualSSL(mutualSSl string) { - adapterInternalAPI.xWso2MutualSSL = mutualSSl +// SetMutualSSL sets the optional or mandatory mTLS +func (swagger *AdapterInternalAPI) SetMutualSSL(mutualSSL string) { + swagger.mutualSSL = mutualSSL } -// GetXWSO2MutualSSL returns the optional or mandatory mTLS -func (adapterInternalAPI *AdapterInternalAPI) GetXWSO2MutualSSL() string { - return adapterInternalAPI.xWso2MutualSSL +// GetMutualSSL returns the optional or mandatory mTLS +func (swagger *AdapterInternalAPI) GetMutualSSL() string { + return swagger.mutualSSL } // SetXWSO2ApplicationSecurity sets the optional or mandatory application security diff --git a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml index 3a289dcb2..fdced4d55 100644 --- a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -105,6 +105,55 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean + mutualSSL: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificateInline: + description: CertificateInline is the Inline Certificate entry + type: string + configMapRef: + description: ConfigMapRef denotes the reference to the ConfigMap + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRef: + description: SecretRef denotes the reference to the Secret + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + - required + type: object type: object override: description: AuthSpec specification of the authentication service @@ -176,6 +225,55 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean + mutualSSL: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificateInline: + description: CertificateInline is the Inline Certificate entry + type: string + configMapRef: + description: ConfigMapRef denotes the reference to the ConfigMap + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRef: + description: SecretRef denotes the reference to the Secret + that contains the Certificate + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + required: + - required + type: object type: object targetRef: description: PolicyTargetReference identifies an API object to apply diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index 22f5faded..b996dde6c 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -74,6 +74,8 @@ const ( configMapBackend = "configMapBackend" configMapAPIDefinition = "configMapAPIDefinition" secretBackend = "secretBackend" + configMapAuthentication = "configMapAuthentication" + secretAuthentication = "secretAuthentication" backendHTTPRouteIndex = "backendHTTPRouteIndex" interceptorServiceAPIPolicyIndex = "interceptorServiceAPIPolicyIndex" backendInterceptorServiceIndex = "backendInterceptorServiceIndex" @@ -344,6 +346,12 @@ func (apiReconciler *APIReconciler) resolveAPIRefs(ctx context.Context, api dpv1 apiRef.String(), namespace, string(api.ObjectMeta.UID), err.Error()) } } + if len(apiState.Authentications) > 0 { + if apiState.MutualSSL, err = apiReconciler.resolveAuthentications(ctx, apiState.Authentications); err != nil { + return nil, fmt.Errorf("error while resolving authentication %v in namespace: %s was not found. %s", + apiState.Authentications, namespace, err.Error()) + } + } if len(prodRouteRefs) > 0 && apiState.APIDefinition.Spec.APIType == "REST" { apiState.ProdHTTPRoute = &synchronizer.HTTPRouteState{} @@ -903,6 +911,33 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context return interceptorServices, backendJWTs, subscriptionValidation, nil } +func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context, + authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) { + resolvedMutualSSL := dpv1alpha1.MutualSSL{} + var err error + var certificate string + for _, authentication := range authentications { + resolvedMutualSSL = utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication) + + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil { + resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required + certificate, err = utils.ResolveCertificate(ctx, apiReconciler.client, + authentication.Namespace, authentication.Spec.Default.MutualSSL.CertificateInline, authentication.Spec.Default.MutualSSL.ConfigMapRef, authentication.Spec.Default.MutualSSL.SecretRef) + } + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil { + resolvedMutualSSL.Required = authentication.Spec.Override.MutualSSL.Required + certificate, err = utils.ResolveCertificate(ctx, apiReconciler.client, + authentication.Namespace, authentication.Spec.Override.MutualSSL.CertificateInline, authentication.Spec.Override.MutualSSL.ConfigMapRef, authentication.Spec.Override.MutualSSL.SecretRef) + } + } + + if err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving client certificate %v in authentication", certificate)) + } + resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, certificate) + return &resolvedMutualSSL, nil +} + func (apiReconciler *APIReconciler) getResolvedBackendsMapping(ctx context.Context, httpRouteState *synchronizer.HTTPRouteState, interceptorServiceMapping map[string]dpv1alpha1.InterceptorService, api dpv1alpha2.API) map[string]*dpv1alpha1.ResolvedBackend { @@ -1116,8 +1151,8 @@ func (apiReconciler *APIReconciler) getAPIsForAuthentication(ctx context.Context return requests } -// getAPIForAuthentication triggers the API controller reconcile method based on the changes detected -// from Authentication objects. If the changes are done for an API stored in the Operator Data store, +// getAPIsForAPIPolicy triggers the API controller reconcile method based on the changes detected +// from APIPolicy objects. If the changes are done for an API stored in the Operator Data store, // a new reconcile event will be created and added to the reconcile event queue. func (apiReconciler *APIReconciler) getAPIsForAPIPolicy(ctx context.Context, obj k8client.Object) []reconcile.Request { apiPolicy, ok := obj.(*dpv1alpha2.APIPolicy) @@ -1200,8 +1235,8 @@ func (apiReconciler *APIReconciler) getAPIsForBackendJWT(ctx context.Context, ob return requests } -// getAPIForAuthentication triggers the API controller reconcile method based on the changes detected -// from Authentication objects. If the changes are done for an API stored in the Operator Data store, +// getAPIsForRateLimitPolicy triggers the API controller reconcile method based on the changes detected +// from RateLimitPolicy objects. If the changes are done for an API stored in the Operator Data store, // a new reconcile event will be created and added to the reconcile event queue. func (apiReconciler *APIReconciler) getAPIsForRateLimitPolicy(ctx context.Context, obj k8client.Object) []reconcile.Request { ratelimitPolicy, ok := obj.(*dpv1alpha1.RateLimitPolicy) @@ -1342,7 +1377,7 @@ func (apiReconciler *APIReconciler) getAPIsForGateway(ctx context.Context, obj k } // addIndexes adds indexing on API, for -// - prodution and sandbox HTTPRoutes +// - production and sandbox HTTPRoutes // referenced in API objects via `.spec.prodHTTPRouteRef` and `.spec.sandHTTPRouteRef` // This helps to find APIs that are affected by a HTTPRoute CRUD operation. // - authentications @@ -1558,6 +1593,60 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { return err } + // Secret to Authentication indexer + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, secretAuthentication, + func(rawObj k8client.Object) []string { + authentication := rawObj.(*dpv1alpha1.Authentication) + var secrets []string + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.SecretRef != nil && len(authentication.Spec.Default.MutualSSL.SecretRef.Name) > 0 { + secrets = append(secrets, + types.NamespacedName{ + Name: string(authentication.Spec.Default.MutualSSL.SecretRef.Name), + Namespace: authentication.Namespace, + }.String()) + + } + + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.SecretRef != nil && len(authentication.Spec.Override.MutualSSL.SecretRef.Name) > 0 { + secrets = append(secrets, + types.NamespacedName{ + Name: string(authentication.Spec.Override.MutualSSL.SecretRef.Name), + Namespace: authentication.Namespace, + }.String()) + + } + return secrets + }); err != nil { + return err + } + + // ConfigMap to Authentication indexer + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, configMapAuthentication, + func(rawObj k8client.Object) []string { + authentication := rawObj.(*dpv1alpha1.Authentication) + var configMaps []string + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.ConfigMapRef != nil && len(authentication.Spec.Default.MutualSSL.ConfigMapRef.Name) > 0 { + configMaps = append(configMaps, + types.NamespacedName{ + Name: string(authentication.Spec.Default.MutualSSL.ConfigMapRef.Name), + Namespace: authentication.Namespace, + }.String()) + + } + + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.ConfigMapRef != nil && len(authentication.Spec.Override.MutualSSL.ConfigMapRef.Name) > 0 { + configMaps = append(configMaps, + types.NamespacedName{ + Name: string(authentication.Spec.Override.MutualSSL.ConfigMapRef.Name), + Namespace: authentication.Namespace, + }.String()) + + } + return configMaps + }); err != nil { + return err + } + // Till the below is httproute rule name and targetref sectionname is supported, // https://gateway-api.sigs.k8s.io/geps/gep-713/?h=multiple+targetrefs#apply-policies-to-sections-of-a-resource-future-extension // we will use a temporary kindName called Resource for policy attachments @@ -1714,20 +1803,20 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { Name: string(apiPolicy.Spec.Override.BackendJWTPolicy.Name), }.String()) } - if apiPolicy.Spec.Default != nil && apiPolicy.Spec.Default.BackendJWTPolicy != nil { - backendJWTs = append(backendJWTs, - types.NamespacedName{ - Namespace: apiPolicy.Namespace, - Name: string(apiPolicy.Spec.Default.BackendJWTPolicy.Name), - }.String()) - } - if apiPolicy.Spec.Override != nil && apiPolicy.Spec.Override.BackendJWTPolicy != nil { - backendJWTs = append(backendJWTs, - types.NamespacedName{ - Namespace: apiPolicy.Namespace, - Name: string(apiPolicy.Spec.Override.BackendJWTPolicy.Name), - }.String()) - } + // if apiPolicy.Spec.Default != nil && apiPolicy.Spec.Default.BackendJWTPolicy != nil { + // backendJWTs = append(backendJWTs, + // types.NamespacedName{ + // Namespace: apiPolicy.Namespace, + // Name: string(apiPolicy.Spec.Default.BackendJWTPolicy.Name), + // }.String()) + // } + // if apiPolicy.Spec.Override != nil && apiPolicy.Spec.Override.BackendJWTPolicy != nil { + // backendJWTs = append(backendJWTs, + // types.NamespacedName{ + // Namespace: apiPolicy.Namespace, + // Name: string(apiPolicy.Spec.Override.BackendJWTPolicy.Name), + // }.String()) + // } return backendJWTs }); err != nil { return err diff --git a/adapter/internal/operator/synchronizer/api_state.go b/adapter/internal/operator/synchronizer/api_state.go index 41e5c2fe4..5490cc505 100644 --- a/adapter/internal/operator/synchronizer/api_state.go +++ b/adapter/internal/operator/synchronizer/api_state.go @@ -43,6 +43,7 @@ type APIState struct { APIDefinitionFile []byte OldOrganizationID string SubscriptionValidation bool + MutualSSL *v1alpha1.MutualSSL } // HTTPRouteState holds the state of the deployed httpRoutes. This state is compared with diff --git a/adapter/internal/operator/synchronizer/rest_api.go b/adapter/internal/operator/synchronizer/rest_api.go index 652e6ac7a..23b413bc7 100644 --- a/adapter/internal/operator/synchronizer/rest_api.go +++ b/adapter/internal/operator/synchronizer/rest_api.go @@ -58,6 +58,10 @@ func GenerateAdapterInternalAPI(apiState APIState, httpRoute *HTTPRouteState, en adapterInternalAPI.SetAPIDefinitionFile(apiState.APIDefinitionFile) adapterInternalAPI.SetAPIDefinitionEndpoint(apiState.APIDefinition.Spec.DefinitionPath) adapterInternalAPI.SetSubscriptionValidation(apiState.SubscriptionValidation) + if apiState.MutualSSL != nil && !adapterInternalAPI.IsSystemAPI { + adapterInternalAPI.SetMutualSSL(apiState.MutualSSL.Required) + adapterInternalAPI.SetClientCerts(apiState.APIDefinition.Name, apiState.MutualSSL.ClientCertificates) + } adapterInternalAPI.EnvType = envType environment := apiState.APIDefinition.Spec.Environment diff --git a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go index eef2fda32..b89dffe25 100644 --- a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go +++ b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go @@ -117,6 +117,11 @@ func (in *APIState) DeepCopyInto(out *APIState) { *out = make([]byte, len(*in)) copy(*out, *in) } + if in.MutualSSL != nil { + in, out := &in.MutualSSL, &out.MutualSSL + *out = new(v1alpha1.MutualSSL) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIState. diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go index c90f88950..44caaf28a 100644 --- a/adapter/internal/operator/utils/utils.go +++ b/adapter/internal/operator/utils/utils.go @@ -455,6 +455,31 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client, return resolvedSecurity } +// GetResolvedMutualSSL resolves backend security configurations. +func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, + authentication dpv1alpha1.Authentication) dpv1alpha1.MutualSSL { + resolvedMutualSSL := dpv1alpha1.MutualSSL{} + var err error + var certificate string + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil { + resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required + certificate, err = ResolveCertificate(ctx, client, + authentication.Namespace, authentication.Spec.Default.MutualSSL.CertificateInline, authentication.Spec.Default.MutualSSL.ConfigMapRef, authentication.Spec.Default.MutualSSL.SecretRef) + } + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil { + resolvedMutualSSL.Required = authentication.Spec.Override.MutualSSL.Required + certificate, err = ResolveCertificate(ctx, client, + authentication.Namespace, authentication.Spec.Override.MutualSSL.CertificateInline, authentication.Spec.Override.MutualSSL.ConfigMapRef, authentication.Spec.Override.MutualSSL.SecretRef) + } + + if err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving client certificate %v in authentication", certificate)) + } + resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, certificate) + + return resolvedMutualSSL +} + // ResolveCertificate reads the certificate from TLSConfig, first checks the certificateInline field, // if no value then load the certificate from secretRef using util function called getSecretValue func ResolveCertificate(ctx context.Context, client k8client.Client, namespace string, certificateInline *string, diff --git a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go b/common-go-libs/apis/dp/v1alpha1/mutualSSL.go new file mode 100644 index 000000000..4becb1cd1 --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha1/mutualSSL.go @@ -0,0 +1,24 @@ +/* + * 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 + +// MutualSSL defines the mutual SSL configurations for an API +type MutualSSL struct { + Required string + ClientCertificates []string +} diff --git a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go index 60b8ac15b..6adecc9f3 100644 --- a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go @@ -301,6 +301,11 @@ func (in *AuthSpec) DeepCopyInto(out *AuthSpec) { *out = new(APIAuth) (*in).DeepCopyInto(*out) } + if in.MutualSSL != nil { + in, out := &in.MutualSSL, &out.MutualSSL + *out = new(MutualSSLConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSpec. @@ -1040,6 +1045,56 @@ func (in JWTIssuerMapping) DeepCopy() JWTIssuerMapping { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MutualSSL) DeepCopyInto(out *MutualSSL) { + *out = *in + if in.ClientCertificates != nil { + in, out := &in.ClientCertificates, &out.ClientCertificates + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSL. +func (in *MutualSSL) DeepCopy() *MutualSSL { + if in == nil { + return nil + } + out := new(MutualSSL) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) { + *out = *in + if in.CertificateInline != nil { + in, out := &in.CertificateInline, &out.CertificateInline + *out = new(string) + **out = **in + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(RefConfig) + **out = **in + } + if in.ConfigMapRef != nil { + in, out := &in.ConfigMapRef, &out.ConfigMapRef + *out = new(RefConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSLConfig. +func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig { + if in == nil { + return nil + } + out := new(MutualSSLConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Oauth2Auth) DeepCopyInto(out *Oauth2Auth) { *out = *in From 4badc0a7bcf32801c0c4c13c8ca299f48bcd293d Mon Sep 17 00:00:00 2001 From: sgayangi Date: Thu, 23 Nov 2023 11:25:31 +0530 Subject: [PATCH 03/15] Add cached API updates for MTLS support --- adapter/internal/operator/synchronizer/data_store.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adapter/internal/operator/synchronizer/data_store.go b/adapter/internal/operator/synchronizer/data_store.go index 9f09a9ed7..80265707d 100644 --- a/adapter/internal/operator/synchronizer/data_store.go +++ b/adapter/internal/operator/synchronizer/data_store.go @@ -150,6 +150,7 @@ func (ods *OperatorDataStore) processAPIState(apiNamespacedName types.Namespaced } if len(apiState.Authentications) != len(cachedAPI.Authentications) { cachedAPI.Authentications = apiState.Authentications + cachedAPI.MutualSSL = apiState.MutualSSL updated = true events = append(events, "Authentications") } else { @@ -157,12 +158,14 @@ func (ods *OperatorDataStore) processAPIState(apiNamespacedName types.Namespaced if existingAuth, found := cachedAPI.Authentications[key]; found { if auth.UID != existingAuth.UID || auth.Generation > existingAuth.Generation { cachedAPI.Authentications = apiState.Authentications + cachedAPI.MutualSSL = apiState.MutualSSL updated = true events = append(events, "Authentications") break } } else { cachedAPI.Authentications = apiState.Authentications + cachedAPI.MutualSSL = apiState.MutualSSL updated = true events = append(events, "Authentications") break From b6bbc8439534632107ea3e2ef6b1c6361f676b07 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Thu, 23 Nov 2023 11:28:42 +0530 Subject: [PATCH 04/15] Add: config values for downstream MTLS --- adapter/resources/conf/config.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/adapter/resources/conf/config.toml b/adapter/resources/conf/config.toml index dc0465cb1..0f2ec8f93 100644 --- a/adapter/resources/conf/config.toml +++ b/adapter/resources/conf/config.toml @@ -28,6 +28,10 @@ verifyHostName = true disableSslVerification = false +[router.downstream] +[router.downstream.tls] +mtlsAPIsEnabled = false +trustedCertPath = "/etc/ssl/certs/ca-certificates.crt" [enforcer.security] [[enforcer.security.tokenService]] From 5f563e91472659616be5201ee543fd8e642b283f Mon Sep 17 00:00:00 2001 From: sgayangi Date: Mon, 27 Nov 2023 09:30:26 +0530 Subject: [PATCH 05/15] Remove mtls certificate tier --- .../wso2/discovery/api/Certificate.proto | 3 +- .../internal/oasparser/config_generator.go | 1 - .../oasparser/model/adapter_internal_api.go | 1 - .../api/wso2/discovery/api/Certificate.pb.go | 33 ++-- .../apk/enforcer/commons/model/APIConfig.java | 21 +-- .../org/wso2/apk/enforcer/api/RestAPI.java | 7 +- .../enforcer/discovery/api/Certificate.java | 152 +----------------- .../discovery/api/CertificateOrBuilder.java | 14 +- .../discovery/api/CertificateProto.java | 13 +- .../security/mtls/MTLSAuthenticator.java | 8 - 10 files changed, 31 insertions(+), 222 deletions(-) diff --git a/adapter/api/proto/wso2/discovery/api/Certificate.proto b/adapter/api/proto/wso2/discovery/api/Certificate.proto index e6421186f..34385aa31 100644 --- a/adapter/api/proto/wso2/discovery/api/Certificate.proto +++ b/adapter/api/proto/wso2/discovery/api/Certificate.proto @@ -28,6 +28,5 @@ option java_multiple_files = true; // Certificates config model message Certificate { string alias = 1; - string tier = 2; - bytes content = 3; + bytes content = 2; } diff --git a/adapter/internal/oasparser/config_generator.go b/adapter/internal/oasparser/config_generator.go index fd8099ddb..050a73901 100644 --- a/adapter/internal/oasparser/config_generator.go +++ b/adapter/internal/oasparser/config_generator.go @@ -168,7 +168,6 @@ func GetEnforcerAPI(adapterInternalAPI model.AdapterInternalAPI, vhost string) * for _, cert := range adapterInternalAPI.GetClientCerts() { certificate := &api.Certificate{ Alias: cert.Alias, - Tier: cert.Tier, Content: cert.Content, } clientCertificates = append(clientCertificates, certificate) diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go index b6165a471..1b44664a9 100644 --- a/adapter/internal/oasparser/model/adapter_internal_api.go +++ b/adapter/internal/oasparser/model/adapter_internal_api.go @@ -227,7 +227,6 @@ type InterceptEndpoint struct { // Certificate contains information of a client certificate type Certificate struct { Alias string - Tier string Content []byte } diff --git a/adapter/pkg/discovery/api/wso2/discovery/api/Certificate.pb.go b/adapter/pkg/discovery/api/wso2/discovery/api/Certificate.pb.go index e0e7aae0e..e316804df 100644 --- a/adapter/pkg/discovery/api/wso2/discovery/api/Certificate.pb.go +++ b/adapter/pkg/discovery/api/wso2/discovery/api/Certificate.pb.go @@ -43,8 +43,7 @@ type Certificate struct { unknownFields protoimpl.UnknownFields Alias string `protobuf:"bytes,1,opt,name=alias,proto3" json:"alias,omitempty"` - Tier string `protobuf:"bytes,2,opt,name=tier,proto3" json:"tier,omitempty"` - Content []byte `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` + Content []byte `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` } func (x *Certificate) Reset() { @@ -86,13 +85,6 @@ func (x *Certificate) GetAlias() string { return "" } -func (x *Certificate) GetTier() string { - if x != nil { - return x.Tier - } - return "" -} - func (x *Certificate) GetContent() []byte { if x != nil { return x.Content @@ -106,20 +98,19 @@ var file_wso2_discovery_api_Certificate_proto_rawDesc = []byte{ 0x0a, 0x24, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x22, 0x51, 0x0a, 0x0b, 0x43, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x22, 0x3d, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x78, 0x0a, - 0x23, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, - 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x2e, 0x61, 0x70, 0x69, 0x42, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, - 0x67, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, - 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x78, 0x0a, 0x23, 0x6f, 0x72, 0x67, + 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, + 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, + 0x42, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, 0x6f, 0x2d, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x77, 0x73, 0x6f, + 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x3b, + 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java index 63cd27902..a3735286e 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java +++ b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java @@ -46,7 +46,6 @@ public class APIConfig { private List resources = new ArrayList<>(); private boolean isMockedApi; private KeyStore trustStore; - private Map mtlsCertificateTiers = new HashMap<>(); private String mutualSSL; private boolean applicationSecurity; private GraphQLSchemaDTO graphQLSchemaDTO; @@ -196,14 +195,6 @@ public KeyStore getTrustStore() { return trustStore; } - /** - * Returns the tier map of mutual ssl certificates for the corresponding API. - * - * @return Tier Map - */ - public Map getMtlsCertificateTiers() { - return mtlsCertificateTiers; - } /** * Returns the mTLS optionality for the corresponding API. @@ -284,7 +275,6 @@ public static class Builder { private List resources = new ArrayList<>(); private boolean isMockedApi; private KeyStore trustStore; - private Map mtlsCertificateTiers; private String mutualSSL; private boolean applicationSecurity; private GraphQLSchemaDTO graphQLSchemaDTO; @@ -372,11 +362,6 @@ public Builder trustStore(KeyStore trustStore) { return this; } - public Builder mtlsCertificateTiers(Map mtlsCertificateTiers) { - this.mtlsCertificateTiers = mtlsCertificateTiers; - return this; - } - public Builder mutualSSL(String mutualSSL) { this.mutualSSL = mutualSSL; return this; @@ -386,7 +371,8 @@ public Builder applicationSecurity(boolean applicationSecurity) { this.applicationSecurity = applicationSecurity; return this; } - public Builder systemAPI(boolean systemAPI){ + + public Builder systemAPI(boolean systemAPI) { this.systemAPI = systemAPI; return this; } @@ -428,11 +414,10 @@ public APIConfig build() { apiConfig.uuid = this.uuid; apiConfig.isMockedApi = this.isMockedApi; apiConfig.trustStore = this.trustStore; - apiConfig.mtlsCertificateTiers = this.mtlsCertificateTiers; apiConfig.mutualSSL = this.mutualSSL; apiConfig.applicationSecurity = this.applicationSecurity; apiConfig.graphQLSchemaDTO = this.graphQLSchemaDTO; - apiConfig.systemAPI = this.systemAPI; + apiConfig.systemAPI = this.systemAPI; apiConfig.jwtConfigurationDto = this.jwtConfigurationDto; apiConfig.apiDefinition = this.apiDefinition; apiConfig.environment = this.environment; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java index ab6d9d578..6071b518c 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java @@ -79,7 +79,6 @@ public String init(Api api) { String version = api.getVersion(); String apiType = api.getApiType(); List resources = new ArrayList<>(); - Map mtlsCertificateTiers = new HashMap<>(); String mutualSSL = api.getMutualSSL(); boolean applicationSecurity = api.getApplicationSecurity(); @@ -100,10 +99,6 @@ public String init(Api api) { throw new SecurityException(e); } - for (Certificate certificate : api.getClientCertificatesList()) { - mtlsCertificateTiers.put(certificate.getAlias(), certificate.getTier()); - } - BackendJWTTokenInfo backendJWTTokenInfo = api.getBackendJWTTokenInfo(); JWTConfigurationDto jwtConfigurationDto = new JWTConfigurationDto(); @@ -131,7 +126,7 @@ public String init(Api api) { .resources(resources).apiType(apiType).tier(api.getTier()) .envType(api.getEnvType()).disableAuthentication(api.getDisableAuthentications()) .disableScopes(api.getDisableScopes()).trustStore(trustStore).organizationId(api.getOrganizationId()) - .mtlsCertificateTiers(mtlsCertificateTiers).mutualSSL(mutualSSL).systemAPI(api.getSystemAPI()) + .mutualSSL(mutualSSL).systemAPI(api.getSystemAPI()) .applicationSecurity(applicationSecurity).jwtConfigurationDto(jwtConfigurationDto) .apiDefinition(apiDefinition).environment(api.getEnvironment()) .subscriptionValidation(api.getSubscriptionValidation()).build(); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Certificate.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Certificate.java index 0a4eeeb8d..f53500587 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Certificate.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Certificate.java @@ -21,7 +21,6 @@ private Certificate(com.google.protobuf.GeneratedMessageV3.Builder builder) { } private Certificate() { alias_ = ""; - tier_ = ""; content_ = com.google.protobuf.ByteString.EMPTY; } @@ -62,12 +61,6 @@ private Certificate( break; } case 18: { - java.lang.String s = input.readStringRequireUtf8(); - - tier_ = s; - break; - } - case 26: { content_ = input.readBytes(); break; @@ -142,48 +135,10 @@ public java.lang.String getAlias() { } } - public static final int TIER_FIELD_NUMBER = 2; - private volatile java.lang.Object tier_; - /** - * string tier = 2; - * @return The tier. - */ - @java.lang.Override - public java.lang.String getTier() { - java.lang.Object ref = tier_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tier_ = s; - return s; - } - } - /** - * string tier = 2; - * @return The bytes for tier. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTierBytes() { - java.lang.Object ref = tier_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tier_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTENT_FIELD_NUMBER = 3; + public static final int CONTENT_FIELD_NUMBER = 2; private com.google.protobuf.ByteString content_; /** - * bytes content = 3; + * bytes content = 2; * @return The content. */ @java.lang.Override @@ -208,11 +163,8 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!getAliasBytes().isEmpty()) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, alias_); } - if (!getTierBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 2, tier_); - } if (!content_.isEmpty()) { - output.writeBytes(3, content_); + output.writeBytes(2, content_); } unknownFields.writeTo(output); } @@ -226,12 +178,9 @@ public int getSerializedSize() { if (!getAliasBytes().isEmpty()) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, alias_); } - if (!getTierBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, tier_); - } if (!content_.isEmpty()) { size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, content_); + .computeBytesSize(2, content_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -250,8 +199,6 @@ public boolean equals(final java.lang.Object obj) { if (!getAlias() .equals(other.getAlias())) return false; - if (!getTier() - .equals(other.getTier())) return false; if (!getContent() .equals(other.getContent())) return false; if (!unknownFields.equals(other.unknownFields)) return false; @@ -267,8 +214,6 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + ALIAS_FIELD_NUMBER; hash = (53 * hash) + getAlias().hashCode(); - hash = (37 * hash) + TIER_FIELD_NUMBER; - hash = (53 * hash) + getTier().hashCode(); hash = (37 * hash) + CONTENT_FIELD_NUMBER; hash = (53 * hash) + getContent().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); @@ -410,8 +355,6 @@ public Builder clear() { super.clear(); alias_ = ""; - tier_ = ""; - content_ = com.google.protobuf.ByteString.EMPTY; return this; @@ -441,7 +384,6 @@ public org.wso2.apk.enforcer.discovery.api.Certificate build() { public org.wso2.apk.enforcer.discovery.api.Certificate buildPartial() { org.wso2.apk.enforcer.discovery.api.Certificate result = new org.wso2.apk.enforcer.discovery.api.Certificate(this); result.alias_ = alias_; - result.tier_ = tier_; result.content_ = content_; onBuilt(); return result; @@ -495,10 +437,6 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Certificate other) alias_ = other.alias_; onChanged(); } - if (!other.getTier().isEmpty()) { - tier_ = other.tier_; - onChanged(); - } if (other.getContent() != com.google.protobuf.ByteString.EMPTY) { setContent(other.getContent()); } @@ -607,85 +545,9 @@ public Builder setAliasBytes( return this; } - private java.lang.Object tier_ = ""; - /** - * string tier = 2; - * @return The tier. - */ - public java.lang.String getTier() { - java.lang.Object ref = tier_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tier_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * string tier = 2; - * @return The bytes for tier. - */ - public com.google.protobuf.ByteString - getTierBytes() { - java.lang.Object ref = tier_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tier_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string tier = 2; - * @param value The tier to set. - * @return This builder for chaining. - */ - public Builder setTier( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - tier_ = value; - onChanged(); - return this; - } - /** - * string tier = 2; - * @return This builder for chaining. - */ - public Builder clearTier() { - - tier_ = getDefaultInstance().getTier(); - onChanged(); - return this; - } - /** - * string tier = 2; - * @param value The bytes for tier to set. - * @return This builder for chaining. - */ - public Builder setTierBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - tier_ = value; - onChanged(); - return this; - } - private com.google.protobuf.ByteString content_ = com.google.protobuf.ByteString.EMPTY; /** - * bytes content = 3; + * bytes content = 2; * @return The content. */ @java.lang.Override @@ -693,7 +555,7 @@ public com.google.protobuf.ByteString getContent() { return content_; } /** - * bytes content = 3; + * bytes content = 2; * @param value The content to set. * @return This builder for chaining. */ @@ -707,7 +569,7 @@ public Builder setContent(com.google.protobuf.ByteString value) { return this; } /** - * bytes content = 3; + * bytes content = 2; * @return This builder for chaining. */ public Builder clearContent() { diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateOrBuilder.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateOrBuilder.java index a8e92bca1..51080ae9f 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateOrBuilder.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateOrBuilder.java @@ -20,19 +20,7 @@ public interface CertificateOrBuilder extends getAliasBytes(); /** - * string tier = 2; - * @return The tier. - */ - java.lang.String getTier(); - /** - * string tier = 2; - * @return The bytes for tier. - */ - com.google.protobuf.ByteString - getTierBytes(); - - /** - * bytes content = 3; + * bytes content = 2; * @return The content. */ com.google.protobuf.ByteString getContent(); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateProto.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateProto.java index c0028b109..484d5794a 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateProto.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/CertificateProto.java @@ -29,12 +29,11 @@ public static void registerAllExtensions( static { java.lang.String[] descriptorData = { "\n$wso2/discovery/api/Certificate.proto\022\022" + - "wso2.discovery.api\";\n\013Certificate\022\r\n\005ali" + - "as\030\001 \001(\t\022\014\n\004tier\030\002 \001(\t\022\017\n\007content\030\003 \001(\014B" + - "x\n#org.wso2.apk.enforcer.discovery.apiB\020" + - "CertificateProtoP\001Z=github.com/envoyprox" + - "y/go-control-plane/wso2/discovery/api;ap" + - "ib\006proto3" + "wso2.discovery.api\"-\n\013Certificate\022\r\n\005ali" + + "as\030\001 \001(\t\022\017\n\007content\030\002 \001(\014Bx\n#org.wso2.ap" + + "k.enforcer.discovery.apiB\020CertificatePro" + + "toP\001Z=github.com/envoyproxy/go-control-p" + + "lane/wso2/discovery/api;apib\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -45,7 +44,7 @@ public static void registerAllExtensions( internal_static_wso2_discovery_api_Certificate_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_wso2_discovery_api_Certificate_descriptor, - new java.lang.String[] { "Alias", "Tier", "Content", }); + new java.lang.String[] { "Alias", "Content", }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/mtls/MTLSAuthenticator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/mtls/MTLSAuthenticator.java index 01ab0324f..4dfab7c43 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/mtls/MTLSAuthenticator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/mtls/MTLSAuthenticator.java @@ -101,14 +101,6 @@ public AuthenticationContext authenticate(RequestContext requestContext) throws } if (!Objects.isNull(clientCert)) { authenticated = true; - String clientCertificateTier = ""; - if (requestContext.getMatchedAPI().getMtlsCertificateTiers().containsKey(clientCertificateAlias)) { - clientCertificateTier = requestContext.getMatchedAPI().getMtlsCertificateTiers() - .get(clientCertificateAlias); - } - if (StringUtils.isNotBlank(clientCertificateTier)) { - authenticationContext.setTier(clientCertificateTier); - } String subjectDN = clientCert.getSubjectDN().getName(); authenticationContext.setUsername(subjectDN); } From d6b6156cb5938ecccfee48a354cd1dc057045d0d Mon Sep 17 00:00:00 2001 From: sgayangi Date: Sun, 3 Dec 2023 14:04:50 +0530 Subject: [PATCH 06/15] Update schema to support mTLS --- .../ballerina/resources/apk-conf-schema.yaml | 217 +++++++++++------- .../ballerina/tests/resources/apk-schema.json | 92 ++++++++ .../config-deployer/conf/apk-schema.json | 92 ++++++++ runtime/runtime-ui/schema/apk-conf.yaml | 63 +++++ runtime/runtime-ui/schema/apk-schema.json | 92 ++++++++ 5 files changed, 474 insertions(+), 82 deletions(-) diff --git a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml index 380cf6c4e..99f170d3c 100644 --- a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml +++ b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml @@ -67,6 +67,41 @@ components: type: array items: $ref: "#/components/schemas/AuthenticationRequest" + transportSecurity: + type: object + properties: + securityType: + type: string + enum: + - mTLS + description: The type of transport security. + required: + type: string + enum: + - mandatory + - optional + description: Specifies whether mTLS is mandatory or optional + secrets: + type: array + description: The names and keys of the secrets containing the mTLS certificates of that API + items: + type: object + properties: + secretName: + type: string + secretKey: + type: string + configMaps: + type: array + description: The names and keys of the config maps containing the mTLS certificates of that API + items: + type: object + properties: + configMapName: + type: string + configMapKey: + type: string + additionalProperties: false additionalProperties: type: array description: Map of custom properties of API @@ -103,43 +138,61 @@ components: additionalProperties: false OAuth2Authentication: allOf: - - $ref: '#/components/schemas/Authentication' - - type: object - properties: - sendTokenToUpstream: - type: boolean - default: false - headerName: - type: string - example: Authorization - default: Authorization - headerEnable: - type: boolean - default: true - additionalProperties: false + - $ref: "#/components/schemas/Authentication" + - type: object + properties: + sendTokenToUpstream: + type: boolean + default: false + headerName: + type: string + example: Authorization + default: Authorization + headerEnable: + type: boolean + default: true + additionalProperties: false APIKeyAuthentication: allOf: - - $ref: '#/components/schemas/Authentication' - - type: object - properties: - sendTokenToUpstream: - type: boolean - default: false - headerName: - type: string - example: Authorization - default: apikey - queryParamName: - type: string - example: apikey - default: apikey - headerEnable: - type: boolean - default: true - queryParamEnable: - type: boolean - default: true - additionalProperties: false + - $ref: "#/components/schemas/Authentication" + - type: object + properties: + sendTokenToUpstream: + type: boolean + default: false + headerName: + type: string + example: Authorization + default: apikey + queryParamName: + type: string + example: apikey + default: apikey + headerEnable: + type: boolean + default: true + queryParamEnable: + type: boolean + default: true + additionalProperties: false + mTLS: + type: object + properties: + required: + type: string + default: optional + enum: + - mandatory + - optional + secrets: + type: array + example: [] + default: [] + configMaps: + type: array + example: [] + default: [] + additionalProperties: false CORSConfiguration: type: object description: | @@ -224,9 +277,9 @@ components: type: string description: Unit of time enum: - - Minute - - Hour - - Day + - Minute + - Hour + - Day example: Minute additionalProperties: false EndpointConfigurations: @@ -373,60 +426,60 @@ components: InterceptorPolicy: title: Interceptor Parameters allOf: - - $ref: "#/components/schemas/BaseOperationPolicy" - - type: object - properties: - parameters: - type: object - properties: - backendUrl: - type: string - headersEnabled: - type: boolean - bodyEnabled: - type: boolean - trailersEnabled: - type: boolean - contextEnabled: - type: boolean - tlsSecretName: - type: string - tlsSecretKey: - type: string - additionalProperties: false + - $ref: "#/components/schemas/BaseOperationPolicy" + - type: object + properties: + parameters: + type: object + properties: + backendUrl: + type: string + headersEnabled: + type: boolean + bodyEnabled: + type: boolean + trailersEnabled: + type: boolean + contextEnabled: + type: boolean + tlsSecretName: + type: string + tlsSecretKey: + type: string + additionalProperties: false required: - - backendUrl + - backendUrl additionalProperties: false BackendJWTPolicy: title: Backend JWT Parameters allOf: - - $ref: "#/components/schemas/BaseOperationPolicy" - - type: object - properties: - parameters: - type: object - properties: - encoding: - type: string - signingAlgorithm: - type: string - header: - type: string - tokenTTL: - type: integer - customClaims: - type: array - items: - "$ref": "#/components/schemas/CustomClaims" - additionalProperties: false + - $ref: "#/components/schemas/BaseOperationPolicy" + - type: object + properties: + parameters: + type: object + properties: + encoding: + type: string + signingAlgorithm: + type: string + header: + type: string + tokenTTL: + type: integer + customClaims: + type: array + items: + "$ref": "#/components/schemas/CustomClaims" + additionalProperties: false required: - - enabled + - enabled additionalProperties: false CustomClaims: type: object required: - - claim - - value + - claim + - value properties: claim: type: string diff --git a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json index 8cc6f4a28..2bdd547df 100644 --- a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json +++ b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json @@ -76,6 +76,57 @@ "$ref": "#/schemas/Authentication" } }, + "transportSecurity": { + "type": "object", + "properties": { + "securityType": { + "type": "string", + "enum": [ + "mTLS" + ], + "description": "The type of transport security." + }, + "required": { + "type": "string", + "enum": [ + "mandatory", + "optional" + ], + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -137,6 +188,47 @@ }, "additionalProperties": false }, + "mTLS": { + "type": "object", + "properties": { + "required": { + "type": "string", + "example": "mandatory", + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "CORSConfiguration": { "type": "object", "description": "Cross-Origin Resource Sharing (CORS) configuration for the API.", diff --git a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json index fabed773c..89dcdd2cf 100644 --- a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json +++ b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json @@ -76,6 +76,57 @@ "$ref": "#/schemas/Authentication" } }, + "transportSecurity": { + "type": "object", + "properties": { + "securityType": { + "type": "string", + "enum": [ + "mTLS" + ], + "description": "The type of transport security." + }, + "required": { + "type": "string", + "enum": [ + "mandatory", + "optional" + ], + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -137,6 +188,47 @@ }, "additionalProperties": false }, + "mTLS": { + "type": "object", + "properties": { + "required": { + "type": "string", + "example": "mandatory", + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "CORSConfiguration": { "type": "object", "description": "Cross-Origin Resource Sharing (CORS) configuration for the API.", diff --git a/runtime/runtime-ui/schema/apk-conf.yaml b/runtime/runtime-ui/schema/apk-conf.yaml index fe75736ab..ab95b3848 100644 --- a/runtime/runtime-ui/schema/apk-conf.yaml +++ b/runtime/runtime-ui/schema/apk-conf.yaml @@ -58,6 +58,41 @@ properties: type: array items: "$ref": "#/schemas/Authentication" + transportSecurity: + type: object + properties: + securityType: + type: string + enum: + - mTLS + description: The type of transport security. + required: + type: string + enum: + - mandatory + - optional + description: Specifies whether mTLS is mandatory or optional + secrets: + type: array + description: The names and keys of the secrets containing the mTLS certificates of that API + items: + type: object + properties: + secretName: + type: string + secretKey: + type: string + configMaps: + type: array + description: The names and keys of the config maps containing the mTLS certificates of that API + items: + type: object + properties: + configMapName: + type: string + configMapKey: + type: string + additionalProperties: false additionalProperties: type: array description: Map of custom properties of API @@ -113,6 +148,34 @@ schemas: Specifies whether the authentication token can be sent as a query parameter. additionalProperties: false + mTLS: + type: object + properties: + required: + type: string + example: mandatory + description: Specifies whether mTLS is mandatory or optional. + secrets: + type: array + description: The names and keys of the secrets containing the mTLS certificates of that API. + items: + type: object + properties: + secretName: + type: string + secretKey: + type: string + configMaps: + type: array + description: The names and keys of the secrets containing the mTLS certificates of that API. + items: + type: object + properties: + configMapName: + type: string + configMapKey: + type: string + additionalProperties: false CORSConfiguration: type: object description: Cross-Origin Resource Sharing (CORS) configuration for the API. diff --git a/runtime/runtime-ui/schema/apk-schema.json b/runtime/runtime-ui/schema/apk-schema.json index 2efeddb0c..2aa1a1cc2 100644 --- a/runtime/runtime-ui/schema/apk-schema.json +++ b/runtime/runtime-ui/schema/apk-schema.json @@ -76,6 +76,57 @@ "$ref": "#/schemas/Authentication" } }, + "transportSecurity": { + "type": "object", + "properties": { + "securityType": { + "type": "string", + "enum": [ + "mTLS" + ], + "description": "The type of transport security." + }, + "required": { + "type": "string", + "enum": [ + "mandatory", + "optional" + ], + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -137,6 +188,47 @@ }, "additionalProperties": false }, + "mTLS": { + "type": "object", + "properties": { + "required": { + "type": "string", + "example": "mandatory", + "description": "Specifies whether mTLS is mandatory or optional" + }, + "secrets": { + "type": "array", + "description": "The names and keys of the secrets containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + } + } + } + }, + "configMaps": { + "type": "array", + "description": "The names and keys of the config maps containing the mTLS certificates of that API", + "items": { + "type": "object", + "properties": { + "configMapName": { + "type": "string" + }, + "configMapKey": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false + }, "CORSConfiguration": { "type": "object", "description": "Cross-Origin Resource Sharing (CORS) configuration for the API.", From e4379ae0cb383c4af4eb18d24bf284cf2a118da9 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Sun, 3 Dec 2023 14:06:10 +0530 Subject: [PATCH 07/15] Update config deployer service for mTLS support --- .../ballerina/APIClient.bal | 82 +++++++++++++++++-- .../ballerina/DeployerClient.bal | 26 +++--- .../ballerina/Errors.bal | 36 ++++---- .../modules/model/Authentication.bal | 11 ++- .../ballerina/types.bal | 32 +++++++- 5 files changed, 148 insertions(+), 39 deletions(-) diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal index 0a6fdb796..6631269a1 100644 --- a/runtime/config-deployer-service/ballerina/APIClient.bal +++ b/runtime/config-deployer-service/ballerina/APIClient.bal @@ -36,11 +36,11 @@ public class APIClient { # + api - APKInternalAPI model # + return - APKConf model. public isolated function fromAPIModelToAPKConf(runtimeModels:API api) returns APKConf|error { - string generatedBasePath = api.getName() + api.getVersion(); + string generatedBasePath = api.getName() + api.getVersion(); byte[] data = generatedBasePath.toBytes(); string encodedString = "/" + data.toBase64(); if (encodedString.endsWith("==")) { - encodedString = encodedString.substring(0,encodedString.length()-2); + encodedString = encodedString.substring(0, encodedString.length() - 2); } APKConf apkConf = { name: api.getName(), @@ -102,7 +102,7 @@ public class APIClient { AuthenticationRequest[]? authentication = apkConf.authentication; if authentication is AuthenticationRequest[] { if createdEndpoints != {} { - _ = check self.populateAuthenticationMap(apiArtifact, apkConf, authentication, createdEndpoints, organization); + _ = check self.populateAuthenticationMap(apiArtifact, apkConf, authentication, createdEndpoints, organization); } else { // check if there are resource level endpoints if resourceLevelEndpointConfigList.length() > 0 { @@ -131,6 +131,11 @@ public class APIClient { } } } + TransportSecurityRequest? transportSecurityRequest = apkConf.transportSecurity; + if transportSecurityRequest is TransportSecurityRequest { + _ = check self.populateTransportSecurityMap(apiArtifact, apkConf, transportSecurityRequest, organization); + } + _ = check self.setHttpRoute(apiArtifact, apkConf, createdEndpoints.hasKey(PRODUCTION_TYPE) ? createdEndpoints.get(PRODUCTION_TYPE) : (), uniqueId, PRODUCTION_TYPE, organization); _ = check self.setHttpRoute(apiArtifact, apkConf, createdEndpoints.hasKey(SANDBOX_TYPE) ? createdEndpoints.get(SANDBOX_TYPE) : (), uniqueId, SANDBOX_TYPE, organization); @@ -338,7 +343,7 @@ public class APIClient { private isolated function populateAuthenticationMap(model:APIArtifact apiArtifact, APKConf apkConf, AuthenticationRequest[] authentications, map createdEndpointMap, commons:Organization organization) returns error? { map authenticationMap = {}; - model:AuthenticationExtenstionType authTypes = {}; + model:AuthenticationExtensionType authTypes = {}; foreach AuthenticationRequest authentication in authentications { if authentication.authType == "OAuth2" { OAuth2Authentication oauth2Authentication = check authentication.cloneWithType(OAuth2Authentication); @@ -380,6 +385,63 @@ public class APIClient { apiArtifact.authenticationMap = authenticationMap; } + private isolated function populateTransportSecurityMap(model:APIArtifact apiArtifact, APKConf apkConf, TransportSecurityRequest transportSecurity, + commons:Organization organization) returns error? { + if transportSecurity.securityType == "mTLS" { + MutualSSL mutualSSL = check transportSecurity.cloneWithType(MutualSSL); + if mutualSSL is MutualSSL { + map authenticationMap = apiArtifact.authenticationMap; + log:printInfo("[MUTUAL SSL] Checking for mutual SSL"); + if mutualSSL is MutualSSL { + string authenticationRefName = self.retrieveAuthenticationRefName(apkConf, "mtls", organization); + model:Authentication authentication = { + metadata: { + name: authenticationRefName, + labels: self.getLabels(apkConf, organization) + }, + spec: { + default: { + mutualSSL: { + required: mutualSSL.required + } + }, + targetRef: { + group: "gateway.networking.k8s.io", + kind: "API", + name: apiArtifact.uniqueId + } + } + }; + ConfigMap[]? configMaps = mutualSSL.configMaps; + Secret[]? secrets = mutualSSL.secrets; + if configMaps is ConfigMap[] && configMaps.length() > 0 + { + model:RefConfig[] configMapRefs = []; + foreach ConfigMap configMap in configMaps { + configMapRefs.push({name: configMap.configMapName, key: configMap.configMapKey}); + } + authentication.spec.default.mutualSSL.configMapRefs = configMapRefs; + } + + if secrets is Secret[] && secrets.length() > 0 + { + model:RefConfig[] secretRefs = []; + foreach Secret secret in secrets { + secretRefs.push({name: secret.secretName, key: secret.secretKey}); + } + authentication.spec.default.mutualSSL.secretRefs = secretRefs; + } + authenticationMap[authenticationRefName] = authentication; + } + log:printDebug("Authentication Map:" + authenticationMap.toString()); + apiArtifact.authenticationMap = authenticationMap; + } + } else { + log:printError("Invalid transport security schema provided"); + return e909019(); + } + } + private isolated function generateAndSetAPICRArtifact(model:APIArtifact apiArtifact, APKConf apkConf, commons:Organization organization) { model:API k8sAPI = { metadata: { @@ -1385,11 +1447,15 @@ public class APIClient { private isolated function validateAndRetrieveAPKConfiguration(json apkconfJson) returns APKConf|commons:APKError? { do { runtimeapi:APKConfValidationResponse validationResponse = check apkConfValidator.validate(apkconfJson.toJsonString()); + log:printInfo(apkconfJson.toJsonString()); + log:printInfo(validationResponse.isValidated().toString()); + if validationResponse.isValidated() { APKConf apkConf = check apkconfJson.cloneWithType(APKConf); map errors = {}; self.validateEndpointConfigurations(apkConf, errors); if (errors.length() > 0) { + log:printInfo(apkconfJson.toJsonString()); return e909029(errors); } return apkConf; @@ -1422,9 +1488,9 @@ public class APIClient { operationLevelProductionEndpointAvailable = endpointConfigs.production is EndpointConfiguration; operationLevelSandboxEndpointAvailable = endpointConfigs.sandbox is EndpointConfiguration; } - if (!operationLevelProductionEndpointAvailable && !productionEndpointAvailable) && (!operationLevelSandboxEndpointAvailable && !sandboxEndpointAvailable) { - errors["endpoint"] = "production/sandbox endpoint not available for " + operation.target; - } + if (!operationLevelProductionEndpointAvailable && !productionEndpointAvailable) && (!operationLevelSandboxEndpointAvailable && !sandboxEndpointAvailable) { + errors["endpoint"] = "production/sandbox endpoint not available for " + operation.target; + } } } @@ -1432,7 +1498,7 @@ public class APIClient { public isolated function prepareArtifact(record {|byte[] fileContent; string fileName; anydata...;|}? apkConfiguration, record {|byte[] fileContent; string fileName; anydata...;|}? definitionFile, commons:Organization organization) returns commons:APKError|model:APIArtifact { if apkConfiguration is () || definitionFile is () { - return e909018("Required apkConfiguration ,definitionFile and apiType are not provided"); + return e909018("Required apkConfiguration, definitionFile and apiType are not provided"); } do { APKConf? apkConf = (); diff --git a/runtime/config-deployer-service/ballerina/DeployerClient.bal b/runtime/config-deployer-service/ballerina/DeployerClient.bal index 4c436d118..898865996 100644 --- a/runtime/config-deployer-service/ballerina/DeployerClient.bal +++ b/runtime/config-deployer-service/ballerina/DeployerClient.bal @@ -6,7 +6,7 @@ import ballerina/log; import ballerina/lang.value; public class DeployerClient { - public isolated function handleAPIDeployment(http:Request request,commons:Organization organization) returns commons:APKError|http:Response { + public isolated function handleAPIDeployment(http:Request request, commons:Organization organization) returns commons:APKError|http:Response { do { DeployApiBody deployAPIBody = check self.retrieveDeployApiBody(request); @@ -14,7 +14,7 @@ public class DeployerClient { return e909017(); } APIClient apiclient = new; - model:APIArtifact prepareArtifact = check apiclient.prepareArtifact(deployAPIBody?.apkConfiguration, deployAPIBody?.definitionFile,organization); + model:APIArtifact prepareArtifact = check apiclient.prepareArtifact(deployAPIBody?.apkConfiguration, deployAPIBody?.definitionFile, organization); model:API deployAPIToK8sResult = check self.deployAPIToK8s(prepareArtifact); APKConf aPKConf = check self.getAPKConf(deployAPIBody.apkConfiguration); aPKConf.id = deployAPIToK8sResult.metadata.name; @@ -35,7 +35,7 @@ public class DeployerClient { } } } - public isolated function handleAPIUndeployment(string apiId,commons:Organization organization) returns AcceptedString|BadRequestError|InternalServerErrorError|commons:APKError { + public isolated function handleAPIUndeployment(string apiId, commons:Organization organization) returns AcceptedString|BadRequestError|InternalServerErrorError|commons:APKError { model:Partition|() availablePartitionForAPI = check partitionResolver.getAvailablePartitionForAPI(apiId, ""); if availablePartitionForAPI is model:Partition { model:API|() api = check getK8sAPIByNameAndNamespace(apiId, availablePartitionForAPI.namespace); @@ -116,7 +116,7 @@ public class DeployerClient { } check self.deployScopeCrs(apiArtifact, ownerReference); check self.deployBackendServices(apiArtifact, ownerReference); - check self.deployAuthneticationCRs(apiArtifact, ownerReference); + check self.deployAuthenticationCRs(apiArtifact, ownerReference); check self.deployRateLimitPolicyCRs(apiArtifact, ownerReference); check self.deployInterceptorServiceCRs(apiArtifact, ownerReference); check self.deployBackendJWTConfigs(apiArtifact, ownerReference); @@ -276,7 +276,7 @@ public class DeployerClient { } else if deployScopeResult.statusCode == http:STATUS_CONFLICT { log:printDebug("Scope already exists" + scope.toString()); model:Scope scopeFromK8s = check getScopeCR(scope.metadata.name, apiArtifact?.namespace); - scope.metadata.resourceVersion=scopeFromK8s.metadata.resourceVersion; + scope.metadata.resourceVersion = scopeFromK8s.metadata.resourceVersion; http:Response scopeCR = check updateScopeCR(scope, apiArtifact?.namespace); if scopeCR.statusCode != http:STATUS_OK { json responsePayLoad = check scopeCR.getJsonPayload(); @@ -363,7 +363,7 @@ public class DeployerClient { } else if deployHttpRouteResult.statusCode == http:STATUS_CONFLICT { log:printDebug("HttpRoute already exists" + httpRoute.toString()); model:Httproute httpRouteFromK8s = check getHttpRoute(httpRoute.metadata.name, namespace); - httpRoute.metadata.resourceVersion=httpRouteFromK8s.metadata.resourceVersion; + httpRoute.metadata.resourceVersion = httpRouteFromK8s.metadata.resourceVersion; http:Response httpRouteCR = check updateHttpRoute(httpRoute, namespace); if httpRouteCR.statusCode != http:STATUS_OK { json responsePayLoad = check httpRouteCR.getJsonPayload(); @@ -395,7 +395,7 @@ public class DeployerClient { } } - private isolated function deployAuthneticationCRs(model:APIArtifact apiArtifact, model:OwnerReference ownerReference) returns error? { + private isolated function deployAuthenticationCRs(model:APIArtifact apiArtifact, model:OwnerReference ownerReference) returns error? { string[] keys = apiArtifact.authenticationMap.keys(); log:printDebug("Inside Deploy Authentication CRs" + keys.toString()); foreach string authenticationCrName in keys { @@ -408,7 +408,7 @@ public class DeployerClient { } else if authenticationCrDeployResponse.statusCode == http:STATUS_CONFLICT { log:printDebug("Authentication CR already exists" + authenticationCr.toString()); model:Authentication authenticationCrFromK8s = check getAuthenticationCR(authenticationCr.metadata.name, apiArtifact?.namespace); - authenticationCr.metadata.resourceVersion=authenticationCrFromK8s.metadata.resourceVersion; + authenticationCr.metadata.resourceVersion = authenticationCrFromK8s.metadata.resourceVersion; http:Response authenticationCR = check updateAuthenticationCR(authenticationCr, apiArtifact?.namespace); if authenticationCR.statusCode != http:STATUS_OK { json responsePayLoad = check authenticationCR.getJsonPayload(); @@ -432,7 +432,7 @@ public class DeployerClient { } else if deployServiceResult.statusCode == http:STATUS_CONFLICT { log:printDebug("Backend already exists" + backendService.toString()); model:Backend backendCRFromK8s = check getBackendCR(backendService.metadata.name, apiArtifact?.namespace); - backendService.metadata.resourceVersion=backendCRFromK8s.metadata.resourceVersion; + backendService.metadata.resourceVersion = backendCRFromK8s.metadata.resourceVersion; http:Response backendCR = check updateBackendCR(backendService, apiArtifact?.namespace); if backendCR.statusCode != http:STATUS_OK { json responsePayLoad = check backendCR.getJsonPayload(); @@ -457,7 +457,7 @@ public class DeployerClient { } else if deployConfigMapResult.statusCode == http:STATUS_CONFLICT { log:printDebug("Configmap Already Exists" + definition.toString()); model:ConfigMap configMapFromK8s = check getConfigMap(definition.metadata.name, deployableNamespace); - definition.metadata.resourceVersion=configMapFromK8s.metadata.resourceVersion; + definition.metadata.resourceVersion = configMapFromK8s.metadata.resourceVersion; deployConfigMapResult = check updateConfigMap(definition, deployableNamespace); if deployConfigMapResult.statusCode == http:STATUS_OK { log:printDebug("updated Configmap Successfully" + definition.toString()); @@ -523,7 +523,7 @@ public class DeployerClient { } else if deployRateLimitPolicyResult.statusCode == http:STATUS_CONFLICT { log:printDebug("RateLimitPolicy already exists" + rateLimitPolicy.toString()); model:RateLimitPolicy rateLimitPolicyFromK8s = check getRateLimitPolicyCR(rateLimitPolicy.metadata.name, apiArtifact?.namespace); - rateLimitPolicy.metadata.resourceVersion=rateLimitPolicyFromK8s.metadata.resourceVersion; + rateLimitPolicy.metadata.resourceVersion = rateLimitPolicyFromK8s.metadata.resourceVersion; http:Response rateLimitPolicyCR = check updateRateLimitPolicyCR(rateLimitPolicy, apiArtifact?.namespace); if rateLimitPolicyCR.statusCode != http:STATUS_OK { json responsePayLoad = check rateLimitPolicyCR.getJsonPayload(); @@ -595,7 +595,7 @@ public class DeployerClient { } else if deployAPIPolicyResult.statusCode == http:STATUS_CONFLICT { log:printDebug("InterceptorService already exists" + interceptorService.toString()); model:InterceptorService interceptorServiceFromK8s = check getInterceptorServiceCR(interceptorService.metadata.name, apiArtifact?.namespace); - interceptorService.metadata.resourceVersion=interceptorServiceFromK8s.metadata.resourceVersion; + interceptorService.metadata.resourceVersion = interceptorServiceFromK8s.metadata.resourceVersion; http:Response interceptorServiceCR = check updateInterceptorServiceCR(interceptorService, apiArtifact?.namespace); if interceptorServiceCR.statusCode != http:STATUS_OK { json responsePayLoad = check interceptorServiceCR.getJsonPayload(); @@ -620,7 +620,7 @@ public class DeployerClient { } else if backendJWTCrDeployResponse.statusCode == http:STATUS_CONFLICT { log:printDebug("BackendJWT Config already exists" + backendJwt.toString()); model:BackendJWT backendJWTCrFromK8s = check getBackendJWTCr(backendJwt.metadata.name, apiArtifact?.namespace); - backendJwt.metadata.resourceVersion=backendJWTCrFromK8s.metadata.resourceVersion; + backendJwt.metadata.resourceVersion = backendJWTCrFromK8s.metadata.resourceVersion; http:Response backendJWTCr = check updateBackendJWTCr(backendJwt, apiArtifact?.namespace); if backendJWTCr.statusCode != http:STATUS_OK { json responsePayLoad = check backendJWTCr.getJsonPayload(); diff --git a/runtime/config-deployer-service/ballerina/Errors.bal b/runtime/config-deployer-service/ballerina/Errors.bal index b5155bf7f..8c0857039 100644 --- a/runtime/config-deployer-service/ballerina/Errors.bal +++ b/runtime/config-deployer-service/ballerina/Errors.bal @@ -18,7 +18,6 @@ // Before adding another function for a new error code // make sure there is no already existing error code for that. // If there is an error code for that, reuse it. - import wso2/apk_common_lib as commons; public isolated function e909000(int code, string msg) returns commons:APKError { @@ -39,7 +38,6 @@ public isolated function e909001(string id) returns commons:APKError { ); } - public isolated function e909003() returns commons:APKError { return error commons:APKError("apiId not found in request", code = 909003, @@ -49,7 +47,6 @@ public isolated function e909003() returns commons:APKError { ); } - public isolated function e909005(string 'field) returns commons:APKError { string msg = 'field + " field(s) unavailable"; return error commons:APKError(msg, @@ -81,9 +78,9 @@ public isolated function e909007() returns commons:APKError { public isolated function e909008() returns commons:APKError { return error commons:APKError("Atleast one of the field required", code = 909008, - message = "Atleast one of the field required", + message = "Atleast one of the fields required", statusCode = 406, - description = "Atleast one of the field required" + description = "Atleast one of the fields required" ); } @@ -177,6 +174,15 @@ public isolated function e909018(string msg) returns commons:APKError { ); } +public isolated function e909019() returns commons:APKError { + return error commons:APKError("Invalid transport security schema", + code = 909018, + message = "Invalid transport security schema provided", + statusCode = 406, + description = "Invalid transport security schema provided" + ); +} + public isolated function e909021() returns commons:APKError { return error commons:APKError("Atleast one operation need to specified", code = 909021, @@ -204,8 +210,8 @@ public isolated function e909022(string msg, error? e) returns commons:APKError } } -public isolated function e909029(map errorItems) returns commons:APKError{ -return error commons:APKError("Apk-conf validation failed", +public isolated function e909029(map errorItems) returns commons:APKError { + return error commons:APKError("Apk-conf validation failed", code = 909029, message = "Invalid apk-conf provided", statusCode = 400, @@ -213,6 +219,7 @@ return error commons:APKError("Apk-conf validation failed", moreInfo = errorItems ); } + public isolated function e909024(string policyName) returns commons:APKError { return error commons:APKError("Invalid parameters provided for policy " + policyName, code = 909024, @@ -249,7 +256,6 @@ public isolated function e909040() returns commons:APKError { ); } - public isolated function e909042() returns commons:APKError { return error commons:APKError("Unsupported API type", code = 909042, @@ -259,16 +265,15 @@ public isolated function e909042() returns commons:APKError { ); } - - public isolated function e909052(error e) returns commons:APKError { return error commons:APKError("Error while generating k8s artifact", e, code = 909052, message = "Error while generating k8s artifact", statusCode = 500, - description = "Error while generating k8s artifact:"+ e.message() + description = "Error while generating k8s artifact:" + e.message() ); } + public isolated function e909043() returns commons:APKError { return error commons:APKError("Error occured while generating openapi definition", code = 909043, @@ -277,6 +282,7 @@ public isolated function e909043() returns commons:APKError { description = "Error occured while generating openapi definition" ); } + public isolated function e909044() returns commons:APKError { return error commons:APKError("Invalid url provided for openapi definition", code = 909044, @@ -285,6 +291,7 @@ public isolated function e909044() returns commons:APKError { description = "Invalid url provided for openapi definition" ); } + public isolated function e9090445() returns commons:APKError { return error commons:APKError("Atleast one Vhost need per production or/and sandbox", code = 9090445, @@ -293,11 +300,12 @@ public isolated function e9090445() returns commons:APKError { description = "Atleast one Vhost need per production or/and sandbox" ); } + public isolated function e909028() returns commons:APKError { - return error commons:APKError( "Internal error occured while deploying API", + return error commons:APKError("Internal error occured while deploying API", code = 909028, message = "Internal error occured while deploying API", statusCode = 500, description = "Internal error occured while deploying API" - ); -} \ No newline at end of file + ); +} diff --git a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal index 9950adb94..eea3e7417 100644 --- a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal +++ b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal @@ -30,15 +30,22 @@ public type AuthenticationSpec record { }; public type AuthenticationData record { - AuthenticationExtenstionType authTypes?; + AuthenticationExtensionType authTypes?; boolean disabled?; + MutualSSL mutualSSL?; }; -public type AuthenticationExtenstionType record { +public type AuthenticationExtensionType record { OAuth2Authentication oauth2?; APIKey[] apiKey = []; }; +public type MutualSSL record { + string required; + RefConfig[] configMapRefs?; + RefConfig[] secretRefs?; +}; + public type OAuth2Authentication record { string header?; boolean sendTokenToUpstream?; diff --git a/runtime/config-deployer-service/ballerina/types.bal b/runtime/config-deployer-service/ballerina/types.bal index 771cd105e..f8513b9e7 100644 --- a/runtime/config-deployer-service/ballerina/types.bal +++ b/runtime/config-deployer-service/ballerina/types.bal @@ -162,8 +162,6 @@ public type DefinitionBody record { string apiType?; }; - - # CORS Configuration of API # # + accessControlAllowOrigins - Field Description @@ -224,6 +222,8 @@ public type APKConf record { APKConf_additionalProperties[] additionalProperties?; # CORS Configuration of API CORSConfiguration corsConfiguration?; + // MutualSSL mTLS?; + TransportSecurityRequest transportSecurity?; }; public type InterceptorPolicy_parameters record {| @@ -271,7 +271,35 @@ public type APIKeyAuthentication record {| boolean queryParamEnable = true; |}; +public type TransportSecurityRequest MutualSSL; + +public type TransportSecurity record {| + string securityType; +|}; + +# mTLS configuration of API. +# +# + required - Specifies if downstream mTLS is mandatory or optional. +# + secrets - List of ref names of K8s secrets containing client certs for the API. +# + configMaps - List of ref names of K8s config maps containing client certs for the API. +public type MutualSSL record {| + *TransportSecurity; + string required; + Secret[] secrets?; + ConfigMap[] configMaps?; +|}; + public type Certificate record { string secretName?; string secretKey?; }; + +public type ConfigMap record { + string configMapName; + string configMapKey; +}; + +public type Secret record { + string secretName; + string secretKey; +}; From 147f99af9dcf24d474b0d1da6d0b8faa9d2e4a9b Mon Sep 17 00:00:00 2001 From: sgayangi Date: Sun, 3 Dec 2023 14:07:35 +0530 Subject: [PATCH 08/15] Update adapter impl. for multiple certs in CR --- .../internal/oasparser/model/http_route.go | 2 +- .../bases/dp.wso2.com_authentications.yaml | 154 ++++++++++-------- .../operator/controllers/dp/api_controller.go | 84 +++++----- adapter/internal/operator/utils/utils.go | 46 ++++-- .../apis/dp/v1alpha1/authentication_types.go | 12 +- .../apis/dp/v1alpha1/zz_generated.deepcopy.go | 42 +++-- .../crds/dp.wso2.com_authentications.yaml | 154 ++++++++++-------- 7 files changed, 288 insertions(+), 206 deletions(-) diff --git a/adapter/internal/oasparser/model/http_route.go b/adapter/internal/oasparser/model/http_route.go index 9c18558d3..0977293e9 100644 --- a/adapter/internal/oasparser/model/http_route.go +++ b/adapter/internal/oasparser/model/http_route.go @@ -249,7 +249,7 @@ func getSecurity(authScheme *dpv1alpha1.Authentication) *Authentication { } else { authFound = true } - if authScheme.Spec.Override.AuthTypes.APIKey != nil { + if authScheme.Spec.Override.AuthTypes != nil && authScheme.Spec.Override.AuthTypes.APIKey != nil { authFound = authFound || len(authScheme.Spec.Override.AuthTypes.APIKey) > 0 var apiKeys []APIKey for _, apiKey := range authScheme.Spec.Override.AuthTypes.APIKey { diff --git a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml index fdced4d55..e64357f8d 100644 --- a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -109,25 +109,32 @@ spec: description: MutualSSL is to specify the features and certificates for mutual SSL properties: - certificateInline: - description: CertificateInline is the Inline Certificate entry - type: string - configMapRef: - description: ConfigMapRef denotes the reference to the ConfigMap + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: description: Required indicates whether mutualSSL is mandatory or optional @@ -135,22 +142,26 @@ spec: - mandatory - optional type: string - secretRef: - description: SecretRef denotes the reference to the Secret + secretRefs: + description: SecretRefs denotes the reference to the Secret that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: - required type: object @@ -229,25 +240,32 @@ spec: description: MutualSSL is to specify the features and certificates for mutual SSL properties: - certificateInline: - description: CertificateInline is the Inline Certificate entry - type: string - configMapRef: - description: ConfigMapRef denotes the reference to the ConfigMap + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: description: Required indicates whether mutualSSL is mandatory or optional @@ -255,22 +273,26 @@ spec: - mandatory - optional type: string - secretRef: - description: SecretRef denotes the reference to the Secret + secretRefs: + description: SecretRefs denotes the reference to the Secret that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: - required type: object diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index b996dde6c..a6a84857e 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -914,27 +914,9 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context, authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) { resolvedMutualSSL := dpv1alpha1.MutualSSL{} - var err error - var certificate string for _, authentication := range authentications { resolvedMutualSSL = utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication) - - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil { - resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required - certificate, err = utils.ResolveCertificate(ctx, apiReconciler.client, - authentication.Namespace, authentication.Spec.Default.MutualSSL.CertificateInline, authentication.Spec.Default.MutualSSL.ConfigMapRef, authentication.Spec.Default.MutualSSL.SecretRef) - } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil { - resolvedMutualSSL.Required = authentication.Spec.Override.MutualSSL.Required - certificate, err = utils.ResolveCertificate(ctx, apiReconciler.client, - authentication.Namespace, authentication.Spec.Override.MutualSSL.CertificateInline, authentication.Spec.Override.MutualSSL.ConfigMapRef, authentication.Spec.Override.MutualSSL.SecretRef) - } - } - - if err != nil { - loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving client certificate %v in authentication", certificate)) } - resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, certificate) return &resolvedMutualSSL, nil } @@ -1598,21 +1580,28 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { func(rawObj k8client.Object) []string { authentication := rawObj.(*dpv1alpha1.Authentication) var secrets []string - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.SecretRef != nil && len(authentication.Spec.Default.MutualSSL.SecretRef.Name) > 0 { - secrets = append(secrets, - types.NamespacedName{ - Name: string(authentication.Spec.Default.MutualSSL.SecretRef.Name), - Namespace: authentication.Namespace, - }.String()) - + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.SecretRefs != nil && len(authentication.Spec.Default.MutualSSL.SecretRefs) > 0 { + for _, secret := range authentication.Spec.Default.MutualSSL.SecretRefs { + if len(secret.Name) > 0 { + secrets = append(secrets, + types.NamespacedName{ + Name: string(secret.Name), + Namespace: authentication.Namespace, + }.String()) + } + } } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.SecretRef != nil && len(authentication.Spec.Override.MutualSSL.SecretRef.Name) > 0 { - secrets = append(secrets, - types.NamespacedName{ - Name: string(authentication.Spec.Override.MutualSSL.SecretRef.Name), - Namespace: authentication.Namespace, - }.String()) + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.SecretRefs != nil && len(authentication.Spec.Override.MutualSSL.SecretRefs) > 0 { + for _, secret := range authentication.Spec.Override.MutualSSL.SecretRefs { + if len(secret.Name) > 0 { + secrets = append(secrets, + types.NamespacedName{ + Name: string(secret.Name), + Namespace: authentication.Namespace, + }.String()) + } + } } return secrets @@ -1625,21 +1614,28 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { func(rawObj k8client.Object) []string { authentication := rawObj.(*dpv1alpha1.Authentication) var configMaps []string - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.ConfigMapRef != nil && len(authentication.Spec.Default.MutualSSL.ConfigMapRef.Name) > 0 { - configMaps = append(configMaps, - types.NamespacedName{ - Name: string(authentication.Spec.Default.MutualSSL.ConfigMapRef.Name), - Namespace: authentication.Namespace, - }.String()) - + if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Default.MutualSSL.ConfigMapRefs) > 0 { + for _, configMap := range authentication.Spec.Default.MutualSSL.ConfigMapRefs { + if len(configMap.Name) > 0 { + configMaps = append(configMaps, + types.NamespacedName{ + Name: string(configMap.Name), + Namespace: authentication.Namespace, + }.String()) + } + } } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.ConfigMapRef != nil && len(authentication.Spec.Override.MutualSSL.ConfigMapRef.Name) > 0 { - configMaps = append(configMaps, - types.NamespacedName{ - Name: string(authentication.Spec.Override.MutualSSL.ConfigMapRef.Name), - Namespace: authentication.Namespace, - }.String()) + if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Override.MutualSSL.ConfigMapRefs) > 0 { + for _, configMap := range authentication.Spec.Override.MutualSSL.ConfigMapRefs { + if len(configMap.Name) > 0 { + configMaps = append(configMaps, + types.NamespacedName{ + Name: string(configMap.Name), + Namespace: authentication.Namespace, + }.String()) + } + } } return configMaps diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go index 44caaf28a..565e825b7 100644 --- a/adapter/internal/operator/utils/utils.go +++ b/adapter/internal/operator/utils/utils.go @@ -455,31 +455,55 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client, return resolvedSecurity } -// GetResolvedMutualSSL resolves backend security configurations. -func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, - authentication dpv1alpha1.Authentication) dpv1alpha1.MutualSSL { +// GetResolvedMutualSSL resolves mTLS related security configurations. +func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication) dpv1alpha1.MutualSSL { resolvedMutualSSL := dpv1alpha1.MutualSSL{} var err error var certificate string + var mutualSSL *dpv1alpha1.MutualSSLConfig if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil { - resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required - certificate, err = ResolveCertificate(ctx, client, - authentication.Namespace, authentication.Spec.Default.MutualSSL.CertificateInline, authentication.Spec.Default.MutualSSL.ConfigMapRef, authentication.Spec.Default.MutualSSL.SecretRef) + mutualSSL = authentication.Spec.Default.MutualSSL } if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil { - resolvedMutualSSL.Required = authentication.Spec.Override.MutualSSL.Required - certificate, err = ResolveCertificate(ctx, client, - authentication.Namespace, authentication.Spec.Override.MutualSSL.CertificateInline, authentication.Spec.Override.MutualSSL.ConfigMapRef, authentication.Spec.Override.MutualSSL.SecretRef) + mutualSSL = authentication.Spec.Override.MutualSSL + } + if mutualSSL != nil { + resolvedCertificates := ResolveAllmTLSCertificates(ctx, mutualSSL, certificate, err, client, authentication.Namespace) + resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required + resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, resolvedCertificates...) } if err != nil { - loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving client certificate %v in authentication", certificate)) + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving mutual SSL %v in authentication", certificate)) } - resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, certificate) return resolvedMutualSSL } +// ResolveAllmTLSCertificates resolves all mTLS certificates +func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.MutualSSLConfig, certificate string, err error, client k8client.Client, namespace string) []string { + var resolvedCertificates []string + if mutualSSL.CertificatesInline != nil { + for _, cert := range mutualSSL.CertificatesInline { + certificate, err = ResolveCertificate(ctx, client, namespace, cert, nil, nil) + resolvedCertificates = append(resolvedCertificates, certificate) + } + } + if mutualSSL.ConfigMapRefs != nil { + for _, cert := range mutualSSL.ConfigMapRefs { + certificate, err = ResolveCertificate(ctx, client, namespace, nil, cert, nil) + resolvedCertificates = append(resolvedCertificates, certificate) + } + } + if mutualSSL.SecretRefs != nil { + for _, cert := range mutualSSL.SecretRefs { + certificate, err = ResolveCertificate(ctx, client, namespace, nil, nil, cert) + resolvedCertificates = append(resolvedCertificates, certificate) + } + } + return resolvedCertificates +} + // ResolveCertificate reads the certificate from TLSConfig, first checks the certificateInline field, // if no value then load the certificate from secretRef using util function called getSecretValue func ResolveCertificate(ctx context.Context, client k8client.Client, namespace string, certificateInline *string, diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go index 2ab575fbe..bee0da32d 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go @@ -70,14 +70,14 @@ type MutualSSLConfig struct { // +kubebuilder:validation:Enum=mandatory;optional Required string `json:"required"` - // CertificateInline is the Inline Certificate entry - CertificateInline *string `json:"certificateInline,omitempty"` + // CertificatesInline is the Inline Certificate entry + CertificatesInline []*string `json:"certificatesInline,omitempty"` - // SecretRef denotes the reference to the Secret that contains the Certificate - SecretRef *RefConfig `json:"secretRef,omitempty"` + // SecretRefs denotes the reference to the Secret that contains the Certificate + SecretRefs []*RefConfig `json:"secretRefs,omitempty"` - // ConfigMapRef denotes the reference to the ConfigMap that contains the Certificate - ConfigMapRef *RefConfig `json:"configMapRef,omitempty"` + // ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate + ConfigMapRefs []*RefConfig `json:"configMapRefs,omitempty"` } // TestConsoleKeyAuth Test Console Key Authentication scheme details diff --git a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go index 6adecc9f3..7aec86e79 100644 --- a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go @@ -1068,20 +1068,38 @@ func (in *MutualSSL) DeepCopy() *MutualSSL { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) { *out = *in - if in.CertificateInline != nil { - in, out := &in.CertificateInline, &out.CertificateInline - *out = new(string) - **out = **in + if in.CertificatesInline != nil { + in, out := &in.CertificatesInline, &out.CertificatesInline + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } } - if in.SecretRef != nil { - in, out := &in.SecretRef, &out.SecretRef - *out = new(RefConfig) - **out = **in + if in.SecretRefs != nil { + in, out := &in.SecretRefs, &out.SecretRefs + *out = make([]*RefConfig, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RefConfig) + **out = **in + } + } } - if in.ConfigMapRef != nil { - in, out := &in.ConfigMapRef, &out.ConfigMapRef - *out = new(RefConfig) - **out = **in + if in.ConfigMapRefs != nil { + in, out := &in.ConfigMapRefs, &out.ConfigMapRefs + *out = make([]*RefConfig, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RefConfig) + **out = **in + } + } } } diff --git a/helm-charts/crds/dp.wso2.com_authentications.yaml b/helm-charts/crds/dp.wso2.com_authentications.yaml index fdced4d55..e64357f8d 100644 --- a/helm-charts/crds/dp.wso2.com_authentications.yaml +++ b/helm-charts/crds/dp.wso2.com_authentications.yaml @@ -109,25 +109,32 @@ spec: description: MutualSSL is to specify the features and certificates for mutual SSL properties: - certificateInline: - description: CertificateInline is the Inline Certificate entry - type: string - configMapRef: - description: ConfigMapRef denotes the reference to the ConfigMap + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: description: Required indicates whether mutualSSL is mandatory or optional @@ -135,22 +142,26 @@ spec: - mandatory - optional type: string - secretRef: - description: SecretRef denotes the reference to the Secret + secretRefs: + description: SecretRefs denotes the reference to the Secret that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: - required type: object @@ -229,25 +240,32 @@ spec: description: MutualSSL is to specify the features and certificates for mutual SSL properties: - certificateInline: - description: CertificateInline is the Inline Certificate entry - type: string - configMapRef: - description: ConfigMapRef denotes the reference to the ConfigMap + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: description: Required indicates whether mutualSSL is mandatory or optional @@ -255,22 +273,26 @@ spec: - mandatory - optional type: string - secretRef: - description: SecretRef denotes the reference to the Secret + secretRefs: + description: SecretRefs denotes the reference to the Secret that contains the Certificate - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object + items: + description: RefConfig holds a config for a secret or a + configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array required: - required type: object From 3353a052801ee3529e7a1e9c6974335cd824b691 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Fri, 15 Dec 2023 17:40:07 +0530 Subject: [PATCH 09/15] Update implementation to add mTLS as AuthType --- adapter/config/default_config.go | 2 +- .../bases/dp.wso2.com_authentications.yaml | 248 +++++++++--------- .../operator/controllers/dp/api_controller.go | 16 +- adapter/internal/operator/utils/utils.go | 10 +- .../apis/dp/v1alpha1/authentication_types.go | 17 +- .../apis/dp/v1alpha1/zz_generated.deepcopy.go | 10 +- .../crds/dp.wso2.com_authentications.yaml | 248 +++++++++--------- .../ballerina/APIClient.bal | 64 +---- .../modules/model/Authentication.bal | 4 +- .../ballerina/resources/apk-conf-schema.yaml | 71 ++--- .../ballerina/tests/resources/apk-schema.json | 86 +----- .../ballerina/types.bal | 34 +-- .../config-deployer/conf/apk-schema.json | 86 +----- runtime/runtime-ui/schema/apk-conf.yaml | 51 ++-- runtime/runtime-ui/schema/apk-schema.json | 81 +----- 15 files changed, 357 insertions(+), 671 deletions(-) diff --git a/adapter/config/default_config.go b/adapter/config/default_config.go index 6abd41fd4..3b3200b0d 100644 --- a/adapter/config/default_config.go +++ b/adapter/config/default_config.go @@ -158,7 +158,7 @@ var defaultConfig = &Config{ }, MutualSSL: mutualSSL{ CertificateHeader: "X-WSO2-CLIENT-CERTIFICATE", - EnableClientValidation: true, + EnableClientValidation: false, ClientCertificateEncode: false, EnableOutboundCertificateHeader: false, }, diff --git a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml index e64357f8d..1dbc523a5 100644 --- a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -68,6 +68,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details @@ -105,66 +169,6 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean - mutualSSL: - description: MutualSSL is to specify the features and certificates - for mutual SSL - properties: - certificatesInline: - description: CertificatesInline is the Inline Certificate - entry - items: - type: string - type: array - configMapRefs: - description: ConfigMapRefs denotes the reference to the ConfigMap - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - description: Required indicates whether mutualSSL is mandatory - or optional - enum: - - mandatory - - optional - type: string - secretRefs: - description: SecretRefs denotes the reference to the Secret - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - - required - type: object type: object override: description: AuthSpec specification of the authentication service @@ -199,6 +203,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details @@ -236,66 +304,6 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean - mutualSSL: - description: MutualSSL is to specify the features and certificates - for mutual SSL - properties: - certificatesInline: - description: CertificatesInline is the Inline Certificate - entry - items: - type: string - type: array - configMapRefs: - description: ConfigMapRefs denotes the reference to the ConfigMap - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - description: Required indicates whether mutualSSL is mandatory - or optional - enum: - - mandatory - - optional - type: string - secretRefs: - description: SecretRefs denotes the reference to the Secret - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - - required - type: object type: object targetRef: description: PolicyTargetReference identifies an API object to apply diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index a6a84857e..09d9afd1c 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -1580,8 +1580,8 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { func(rawObj k8client.Object) []string { authentication := rawObj.(*dpv1alpha1.Authentication) var secrets []string - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.SecretRefs != nil && len(authentication.Spec.Default.MutualSSL.SecretRefs) > 0 { - for _, secret := range authentication.Spec.Default.MutualSSL.SecretRefs { + if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs) > 0 { + for _, secret := range authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs { if len(secret.Name) > 0 { secrets = append(secrets, types.NamespacedName{ @@ -1592,8 +1592,8 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.SecretRefs != nil && len(authentication.Spec.Override.MutualSSL.SecretRefs) > 0 { - for _, secret := range authentication.Spec.Override.MutualSSL.SecretRefs { + if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil && authentication.Spec.Override.AuthTypes.MutualSSL.SecretRefs != nil && len(authentication.Spec.Override.AuthTypes.MutualSSL.SecretRefs) > 0 { + for _, secret := range authentication.Spec.Override.AuthTypes.MutualSSL.SecretRefs { if len(secret.Name) > 0 { secrets = append(secrets, types.NamespacedName{ @@ -1614,8 +1614,8 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { func(rawObj k8client.Object) []string { authentication := rawObj.(*dpv1alpha1.Authentication) var configMaps []string - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil && authentication.Spec.Default.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Default.MutualSSL.ConfigMapRefs) > 0 { - for _, configMap := range authentication.Spec.Default.MutualSSL.ConfigMapRefs { + if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs) > 0 { + for _, configMap := range authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs { if len(configMap.Name) > 0 { configMaps = append(configMaps, types.NamespacedName{ @@ -1626,8 +1626,8 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil && authentication.Spec.Override.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Override.MutualSSL.ConfigMapRefs) > 0 { - for _, configMap := range authentication.Spec.Override.MutualSSL.ConfigMapRefs { + if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil && authentication.Spec.Override.AuthTypes.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Override.AuthTypes.MutualSSL.ConfigMapRefs) > 0 { + for _, configMap := range authentication.Spec.Override.AuthTypes.MutualSSL.ConfigMapRefs { if len(configMap.Name) > 0 { configMaps = append(configMaps, types.NamespacedName{ diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go index 565e825b7..dd3c8ea7a 100644 --- a/adapter/internal/operator/utils/utils.go +++ b/adapter/internal/operator/utils/utils.go @@ -461,15 +461,15 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic var err error var certificate string var mutualSSL *dpv1alpha1.MutualSSLConfig - if authentication.Spec.Default != nil && authentication.Spec.Default.MutualSSL != nil { - mutualSSL = authentication.Spec.Default.MutualSSL + if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil { + mutualSSL = authentication.Spec.Default.AuthTypes.MutualSSL } - if authentication.Spec.Override != nil && authentication.Spec.Override.MutualSSL != nil { - mutualSSL = authentication.Spec.Override.MutualSSL + if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil { + mutualSSL = authentication.Spec.Override.AuthTypes.MutualSSL } if mutualSSL != nil { resolvedCertificates := ResolveAllmTLSCertificates(ctx, mutualSSL, certificate, err, client, authentication.Namespace) - resolvedMutualSSL.Required = authentication.Spec.Default.MutualSSL.Required + resolvedMutualSSL.Required = authentication.Spec.Default.AuthTypes.MutualSSL.Required resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, resolvedCertificates...) } diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go index bee0da32d..778f70626 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go @@ -38,11 +38,6 @@ type AuthSpec struct { // AuthTypes is to specify the authentication scheme types and details AuthTypes *APIAuth `json:"authTypes,omitempty"` - - // MutualSSL is to specify the features and certificates for mutual SSL - // - // +optional - MutualSSL *MutualSSLConfig `json:"mutualSSL,omitempty"` } // APIAuth Authentication scheme type and details @@ -62,10 +57,22 @@ type APIAuth struct { // // +optional TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"` + + // MutualSSL is to specify the features and certificates for mutual SSL + // + // +optional + MutualSSL *MutualSSLConfig `json:"mtls,omitempty"` } // MutualSSLConfig scheme type and details type MutualSSLConfig struct { + + // Disabled is to disable mTLS authentication + // + // +kubebuilder:default:=false + // +optional + Disabled bool `json:"disabled,omitempty"` + // Required indicates whether mutualSSL is mandatory or optional // +kubebuilder:validation:Enum=mandatory;optional Required string `json:"required"` diff --git a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go index 7aec86e79..a82496ccf 100644 --- a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go @@ -64,6 +64,11 @@ func (in *APIAuth) DeepCopyInto(out *APIAuth) { copy(*out, *in) } out.TestConsoleKey = in.TestConsoleKey + if in.MutualSSL != nil { + in, out := &in.MutualSSL, &out.MutualSSL + *out = new(MutualSSLConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIAuth. @@ -301,11 +306,6 @@ func (in *AuthSpec) DeepCopyInto(out *AuthSpec) { *out = new(APIAuth) (*in).DeepCopyInto(*out) } - if in.MutualSSL != nil { - in, out := &in.MutualSSL, &out.MutualSSL - *out = new(MutualSSLConfig) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSpec. diff --git a/helm-charts/crds/dp.wso2.com_authentications.yaml b/helm-charts/crds/dp.wso2.com_authentications.yaml index e64357f8d..1dbc523a5 100644 --- a/helm-charts/crds/dp.wso2.com_authentications.yaml +++ b/helm-charts/crds/dp.wso2.com_authentications.yaml @@ -68,6 +68,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details @@ -105,66 +169,6 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean - mutualSSL: - description: MutualSSL is to specify the features and certificates - for mutual SSL - properties: - certificatesInline: - description: CertificatesInline is the Inline Certificate - entry - items: - type: string - type: array - configMapRefs: - description: ConfigMapRefs denotes the reference to the ConfigMap - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - description: Required indicates whether mutualSSL is mandatory - or optional - enum: - - mandatory - - optional - type: string - secretRefs: - description: SecretRefs denotes the reference to the Secret - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - - required - type: object type: object override: description: AuthSpec specification of the authentication service @@ -199,6 +203,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details @@ -236,66 +304,6 @@ spec: disabled: description: Disabled is to disable all authentications type: boolean - mutualSSL: - description: MutualSSL is to specify the features and certificates - for mutual SSL - properties: - certificatesInline: - description: CertificatesInline is the Inline Certificate - entry - items: - type: string - type: array - configMapRefs: - description: ConfigMapRefs denotes the reference to the ConfigMap - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - description: Required indicates whether mutualSSL is mandatory - or optional - enum: - - mandatory - - optional - type: string - secretRefs: - description: SecretRefs denotes the reference to the Secret - that contains the Certificate - items: - description: RefConfig holds a config for a secret or a - configmap - properties: - key: - description: Key of the secret or configmap - minLength: 1 - type: string - name: - description: Name of the secret or configmap - minLength: 1 - type: string - required: - - key - - name - type: object - type: array - required: - - required - type: object type: object targetRef: description: PolicyTargetReference identifies an API object to apply diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal index 6631269a1..bd9309bf3 100644 --- a/runtime/config-deployer-service/ballerina/APIClient.bal +++ b/runtime/config-deployer-service/ballerina/APIClient.bal @@ -131,10 +131,6 @@ public class APIClient { } } } - TransportSecurityRequest? transportSecurityRequest = apkConf.transportSecurity; - if transportSecurityRequest is TransportSecurityRequest { - _ = check self.populateTransportSecurityMap(apiArtifact, apkConf, transportSecurityRequest, organization); - } _ = check self.setHttpRoute(apiArtifact, apkConf, createdEndpoints.hasKey(PRODUCTION_TYPE) ? createdEndpoints.get(PRODUCTION_TYPE) : (), uniqueId, PRODUCTION_TYPE, organization); _ = check self.setHttpRoute(apiArtifact, apkConf, createdEndpoints.hasKey(SANDBOX_TYPE) ? createdEndpoints.get(SANDBOX_TYPE) : (), uniqueId, SANDBOX_TYPE, organization); @@ -353,6 +349,9 @@ public class APIClient { authTypes.apiKey = []; authTypes.apiKey.push({'in: "Header", name: apiKeyAuthentication.headerName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); authTypes.apiKey.push({'in: "Query", name: apiKeyAuthentication.queryParamName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); + } else if authentication.authType == "mTLS" { + MTLSAuthentication mtlsAuthentication = check authentication.cloneWithType(MTLSAuthentication); + authTypes.mtls = {disabled: !mtlsAuthentication.enabled, configMapRefs: mtlsAuthentication.certificates, required: mtlsAuthentication.required}; } } log:printDebug("Auth Types:" + authTypes.toString()); @@ -385,63 +384,6 @@ public class APIClient { apiArtifact.authenticationMap = authenticationMap; } - private isolated function populateTransportSecurityMap(model:APIArtifact apiArtifact, APKConf apkConf, TransportSecurityRequest transportSecurity, - commons:Organization organization) returns error? { - if transportSecurity.securityType == "mTLS" { - MutualSSL mutualSSL = check transportSecurity.cloneWithType(MutualSSL); - if mutualSSL is MutualSSL { - map authenticationMap = apiArtifact.authenticationMap; - log:printInfo("[MUTUAL SSL] Checking for mutual SSL"); - if mutualSSL is MutualSSL { - string authenticationRefName = self.retrieveAuthenticationRefName(apkConf, "mtls", organization); - model:Authentication authentication = { - metadata: { - name: authenticationRefName, - labels: self.getLabels(apkConf, organization) - }, - spec: { - default: { - mutualSSL: { - required: mutualSSL.required - } - }, - targetRef: { - group: "gateway.networking.k8s.io", - kind: "API", - name: apiArtifact.uniqueId - } - } - }; - ConfigMap[]? configMaps = mutualSSL.configMaps; - Secret[]? secrets = mutualSSL.secrets; - if configMaps is ConfigMap[] && configMaps.length() > 0 - { - model:RefConfig[] configMapRefs = []; - foreach ConfigMap configMap in configMaps { - configMapRefs.push({name: configMap.configMapName, key: configMap.configMapKey}); - } - authentication.spec.default.mutualSSL.configMapRefs = configMapRefs; - } - - if secrets is Secret[] && secrets.length() > 0 - { - model:RefConfig[] secretRefs = []; - foreach Secret secret in secrets { - secretRefs.push({name: secret.secretName, key: secret.secretKey}); - } - authentication.spec.default.mutualSSL.secretRefs = secretRefs; - } - authenticationMap[authenticationRefName] = authentication; - } - log:printDebug("Authentication Map:" + authenticationMap.toString()); - apiArtifact.authenticationMap = authenticationMap; - } - } else { - log:printError("Invalid transport security schema provided"); - return e909019(); - } - } - private isolated function generateAndSetAPICRArtifact(model:APIArtifact apiArtifact, APKConf apkConf, commons:Organization organization) { model:API k8sAPI = { metadata: { diff --git a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal index eea3e7417..7fc022be4 100644 --- a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal +++ b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal @@ -32,18 +32,20 @@ public type AuthenticationSpec record { public type AuthenticationData record { AuthenticationExtensionType authTypes?; boolean disabled?; - MutualSSL mutualSSL?; }; public type AuthenticationExtensionType record { OAuth2Authentication oauth2?; APIKey[] apiKey = []; + MutualSSL mtls?; }; public type MutualSSL record { string required; + boolean disabled; RefConfig[] configMapRefs?; RefConfig[] secretRefs?; + string[] certificatesInline?; }; public type OAuth2Authentication record { diff --git a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml index 99f170d3c..43a131efd 100644 --- a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml +++ b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml @@ -67,41 +67,6 @@ components: type: array items: $ref: "#/components/schemas/AuthenticationRequest" - transportSecurity: - type: object - properties: - securityType: - type: string - enum: - - mTLS - description: The type of transport security. - required: - type: string - enum: - - mandatory - - optional - description: Specifies whether mTLS is mandatory or optional - secrets: - type: array - description: The names and keys of the secrets containing the mTLS certificates of that API - items: - type: object - properties: - secretName: - type: string - secretKey: - type: string - configMaps: - type: array - description: The names and keys of the config maps containing the mTLS certificates of that API - items: - type: object - properties: - configMapName: - type: string - configMapKey: - type: string - additionalProperties: false additionalProperties: type: array description: Map of custom properties of API @@ -119,11 +84,13 @@ components: oneOf: - $ref: "#/components/schemas/OAuth2Authentication" - $ref: "#/components/schemas/APIKeyAuthentication" + - $ref: "#/components/schemas/MTLSAuthentication" discriminator: propertyName: authType mapping: OAuth2: "#/components/schemas/OAuth2Authentication" APIKey: "#/components/schemas/APIKeyAuthentication" + mTLS: "#/components/schemas/MTLSAuthentication" Authentication: type: object discriminator: @@ -175,24 +142,22 @@ components: type: boolean default: true additionalProperties: false - mTLS: - type: object - properties: - required: - type: string - default: optional - enum: - - mandatory - - optional - secrets: - type: array - example: [] - default: [] - configMaps: - type: array - example: [] - default: [] - additionalProperties: false + MTLSAuthentication: + allOf: + - $ref: "#/components/schemas/Authentication" + - type: object + properties: + required: + type: string + default: mandatory + enum: + - mandatory + - optional + certificates: + type: array + example: [] + default: [] + additionalProperties: false CORSConfiguration: type: object description: | diff --git a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json index 2bdd547df..53b120c43 100644 --- a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json +++ b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json @@ -76,57 +76,6 @@ "$ref": "#/schemas/Authentication" } }, - "transportSecurity": { - "type": "object", - "properties": { - "securityType": { - "type": "string", - "enum": [ - "mTLS" - ], - "description": "The type of transport security." - }, - "required": { - "type": "string", - "enum": [ - "mandatory", - "optional" - ], - "description": "Specifies whether mTLS is mandatory or optional" - }, - "secrets": { - "type": "array", - "description": "The names and keys of the secrets containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "secretName": { - "type": "string" - }, - "secretKey": { - "type": "string" - } - } - } - }, - "configMaps": { - "type": "array", - "description": "The names and keys of the config maps containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "configMapName": { - "type": "string" - }, - "configMapKey": { - "type": "string" - } - } - } - } - }, - "additionalProperties": false - }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -184,50 +133,29 @@ "queryParamEnable": { "type": "boolean", "description": "Specifies whether the authentication token can be sent as a query parameter." - } - }, - "additionalProperties": false - }, - "mTLS": { - "type": "object", - "properties": { + }, "required": { "type": "string", "example": "mandatory", "description": "Specifies whether mTLS is mandatory or optional" }, - "secrets": { - "type": "array", - "description": "The names and keys of the secrets containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "secretName": { - "type": "string" - }, - "secretKey": { - "type": "string" - } - } - } - }, - "configMaps": { + "certificates": { "type": "array", "description": "The names and keys of the config maps containing the mTLS certificates of that API", "items": { "type": "object", "properties": { - "configMapName": { + "name": { "type": "string" }, - "configMapKey": { + "key": { "type": "string" } } - } + }, + "additionalProperties": false } - }, - "additionalProperties": false + } }, "CORSConfiguration": { "type": "object", diff --git a/runtime/config-deployer-service/ballerina/types.bal b/runtime/config-deployer-service/ballerina/types.bal index f8513b9e7..a32a549a6 100644 --- a/runtime/config-deployer-service/ballerina/types.bal +++ b/runtime/config-deployer-service/ballerina/types.bal @@ -112,7 +112,7 @@ public type CircuitBreaker record { int maxRetries?; }; -public type AuthenticationRequest OAuth2Authentication|APIKeyAuthentication; +public type AuthenticationRequest OAuth2Authentication|APIKeyAuthentication|MTLSAuthentication; public type EndpointConfigurations record { EndpointConfiguration production?; @@ -222,8 +222,6 @@ public type APKConf record { APKConf_additionalProperties[] additionalProperties?; # CORS Configuration of API CORSConfiguration corsConfiguration?; - // MutualSSL mTLS?; - TransportSecurityRequest transportSecurity?; }; public type InterceptorPolicy_parameters record {| @@ -271,22 +269,14 @@ public type APIKeyAuthentication record {| boolean queryParamEnable = true; |}; -public type TransportSecurityRequest MutualSSL; - -public type TransportSecurity record {| - string securityType; -|}; - -# mTLS configuration of API. +# Mutual SSL configuration of this API # -# + required - Specifies if downstream mTLS is mandatory or optional. -# + secrets - List of ref names of K8s secrets containing client certs for the API. -# + configMaps - List of ref names of K8s config maps containing client certs for the API. -public type MutualSSL record {| - *TransportSecurity; +# + required - If mTLS is optional or mandatory +# + certificates - The list of config map refs referring to the client certificates +public type MTLSAuthentication record {| + *Authentication; string required; - Secret[] secrets?; - ConfigMap[] configMaps?; + ConfigMapRef[] certificates; |}; public type Certificate record { @@ -294,12 +284,8 @@ public type Certificate record { string secretKey?; }; -public type ConfigMap record { - string configMapName; - string configMapKey; +public type ConfigMapRef record { + string name; + string key; }; -public type Secret record { - string secretName; - string secretKey; -}; diff --git a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json index 89dcdd2cf..6f036f508 100644 --- a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json +++ b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json @@ -76,57 +76,6 @@ "$ref": "#/schemas/Authentication" } }, - "transportSecurity": { - "type": "object", - "properties": { - "securityType": { - "type": "string", - "enum": [ - "mTLS" - ], - "description": "The type of transport security." - }, - "required": { - "type": "string", - "enum": [ - "mandatory", - "optional" - ], - "description": "Specifies whether mTLS is mandatory or optional" - }, - "secrets": { - "type": "array", - "description": "The names and keys of the secrets containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "secretName": { - "type": "string" - }, - "secretKey": { - "type": "string" - } - } - } - }, - "configMaps": { - "type": "array", - "description": "The names and keys of the config maps containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "configMapName": { - "type": "string" - }, - "configMapKey": { - "type": "string" - } - } - } - } - }, - "additionalProperties": false - }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -184,50 +133,29 @@ "queryParamEnable": { "type": "boolean", "description": "Specifies whether the authentication token can be sent as a query parameter." - } - }, - "additionalProperties": false - }, - "mTLS": { - "type": "object", - "properties": { + }, "required": { "type": "string", "example": "mandatory", "description": "Specifies whether mTLS is mandatory or optional" }, - "secrets": { - "type": "array", - "description": "The names and keys of the secrets containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "secretName": { - "type": "string" - }, - "secretKey": { - "type": "string" - } - } - } - }, - "configMaps": { + "certificates": { "type": "array", "description": "The names and keys of the config maps containing the mTLS certificates of that API", "items": { "type": "object", "properties": { - "configMapName": { + "name": { "type": "string" }, - "configMapKey": { + "key": { "type": "string" } } - } + }, + "additionalProperties": false } - }, - "additionalProperties": false + } }, "CORSConfiguration": { "type": "object", diff --git a/runtime/runtime-ui/schema/apk-conf.yaml b/runtime/runtime-ui/schema/apk-conf.yaml index ab95b3848..23e98266b 100644 --- a/runtime/runtime-ui/schema/apk-conf.yaml +++ b/runtime/runtime-ui/schema/apk-conf.yaml @@ -58,41 +58,6 @@ properties: type: array items: "$ref": "#/schemas/Authentication" - transportSecurity: - type: object - properties: - securityType: - type: string - enum: - - mTLS - description: The type of transport security. - required: - type: string - enum: - - mandatory - - optional - description: Specifies whether mTLS is mandatory or optional - secrets: - type: array - description: The names and keys of the secrets containing the mTLS certificates of that API - items: - type: object - properties: - secretName: - type: string - secretKey: - type: string - configMaps: - type: array - description: The names and keys of the config maps containing the mTLS certificates of that API - items: - type: object - properties: - configMapName: - type: string - configMapKey: - type: string - additionalProperties: false additionalProperties: type: array description: Map of custom properties of API @@ -147,6 +112,22 @@ schemas: description: Specifies whether the authentication token can be sent as a query parameter. + required: + type: string + enum: + - mandatory + - optional + description: Specifies whether mTLS is mandatory or optional + certificates: + type: array + description: The names and keys of the secrets containing the mTLS certificates of that API + items: + type: object + properties: + name: + type: string + key: + type: string additionalProperties: false mTLS: type: object diff --git a/runtime/runtime-ui/schema/apk-schema.json b/runtime/runtime-ui/schema/apk-schema.json index 2aa1a1cc2..56d205072 100644 --- a/runtime/runtime-ui/schema/apk-schema.json +++ b/runtime/runtime-ui/schema/apk-schema.json @@ -76,57 +76,6 @@ "$ref": "#/schemas/Authentication" } }, - "transportSecurity": { - "type": "object", - "properties": { - "securityType": { - "type": "string", - "enum": [ - "mTLS" - ], - "description": "The type of transport security." - }, - "required": { - "type": "string", - "enum": [ - "mandatory", - "optional" - ], - "description": "Specifies whether mTLS is mandatory or optional" - }, - "secrets": { - "type": "array", - "description": "The names and keys of the secrets containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "secretName": { - "type": "string" - }, - "secretKey": { - "type": "string" - } - } - } - }, - "configMaps": { - "type": "array", - "description": "The names and keys of the config maps containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "configMapName": { - "type": "string" - }, - "configMapKey": { - "type": "string" - } - } - } - } - }, - "additionalProperties": false - }, "additionalProperties": { "type": "array", "description": "Map of custom properties of API", @@ -184,19 +133,16 @@ "queryParamEnable": { "type": "boolean", "description": "Specifies whether the authentication token can be sent as a query parameter." - } - }, - "additionalProperties": false - }, - "mTLS": { - "type": "object", - "properties": { + }, "required": { "type": "string", - "example": "mandatory", + "enum": [ + "mandatory", + "optional" + ], "description": "Specifies whether mTLS is mandatory or optional" }, - "secrets": { + "certificates": { "type": "array", "description": "The names and keys of the secrets containing the mTLS certificates of that API", "items": { @@ -210,21 +156,6 @@ } } } - }, - "configMaps": { - "type": "array", - "description": "The names and keys of the config maps containing the mTLS certificates of that API", - "items": { - "type": "object", - "properties": { - "configMapName": { - "type": "string" - }, - "configMapKey": { - "type": "string" - } - } - } } }, "additionalProperties": false From 86f9291527e79897e3248c5ee4fd5ec51bd7bdcf Mon Sep 17 00:00:00 2001 From: sgayangi Date: Sun, 17 Dec 2023 13:44:57 +0530 Subject: [PATCH 10/15] Add webhook for Authentication CR --- .../operator/config/webhook/manifests.yaml | 40 ++++++ .../operator/config/webhook/manifests.yaml | 40 ++++++ .../internal/operator/operator.go | 5 + common-go-libs/PROJECT | 4 + common-go-libs/{READ.ME => README} | 0 .../dp/v1alpha1/authentication_webhook.go | 112 +++++++++++++++ .../apis/dp/v1alpha1/webhook_suite_test.go | 3 + .../bases/dp.wso2.com_authentications.yaml | 128 ++++++++++++++++++ common-go-libs/config/webhook/manifests.yaml | 40 ++++++ .../adapter-mutating-webhook-config.yaml | 20 +++ .../adapter-validation-webhook-config.yaml | 20 +++ .../ballerina/APIClient.bal | 11 ++ .../ballerina/Errors.bal | 6 +- 13 files changed, 426 insertions(+), 3 deletions(-) rename common-go-libs/{READ.ME => README} (100%) create mode 100644 common-go-libs/apis/dp/v1alpha1/authentication_webhook.go diff --git a/adapter/internal/operator/config/webhook/manifests.yaml b/adapter/internal/operator/config/webhook/manifests.yaml index 30633a719..474f6dc2f 100644 --- a/adapter/internal/operator/config/webhook/manifests.yaml +++ b/adapter/internal/operator/config/webhook/manifests.yaml @@ -45,6 +45,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -172,6 +192,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/common-controller/internal/operator/config/webhook/manifests.yaml b/common-controller/internal/operator/config/webhook/manifests.yaml index c7026f4c8..7d86cb224 100644 --- a/common-controller/internal/operator/config/webhook/manifests.yaml +++ b/common-controller/internal/operator/config/webhook/manifests.yaml @@ -64,6 +64,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -210,6 +230,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/common-controller/internal/operator/operator.go b/common-controller/internal/operator/operator.go index bd973ae28..d3414c534 100644 --- a/common-controller/internal/operator/operator.go +++ b/common-controller/internal/operator/operator.go @@ -121,6 +121,11 @@ func InitOperator() { "Unable to create webhook for APIPolicy, error: %v", err)) } + if err = (&dpv1alpha1.Authentication{}).SetupWebhookWithManager(mgr); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2638, logging.MAJOR, + "Unable to create webhook for Authentication, error: %v", err)) + } + if err = (&dpv1alpha1.InterceptorService{}).SetupWebhookWithManager(mgr); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2652, logging.MAJOR, "Unable to create webhook for InterceptorService, error: %v", err)) diff --git a/common-go-libs/PROJECT b/common-go-libs/PROJECT index 8f0e7f9ff..cb1f5622f 100644 --- a/common-go-libs/PROJECT +++ b/common-go-libs/PROJECT @@ -31,6 +31,10 @@ resources: kind: Authentication path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1 version: v1alpha1 + webhooks: + defaulting: true + validation: true + webhookVersion: v1 - api: crdVersion: v1 namespaced: true diff --git a/common-go-libs/READ.ME b/common-go-libs/README similarity index 100% rename from common-go-libs/READ.ME rename to common-go-libs/README diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go new file mode 100644 index 000000000..471102b00 --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go @@ -0,0 +1,112 @@ +/* + * 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 ( + "strings" + + constants "github.com/wso2/apk/common-go-libs/constants" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// SetupWebhookWithManager creates a new webhook builder for Authentication +func (r *Authentication) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +//+kubebuilder:webhook:path=/mutate-dp-wso2-com-v1alpha1-authentication,mutating=true,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha1,name=mauthentication.kb.io,admissionReviewVersions=v1 + +var _ webhook.Defaulter = &Authentication{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *Authentication) Default() { + // TODO(user): fill in your defaulting logic. +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-dp-wso2-com-v1alpha1-authentication,mutating=false,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha1,name=vauthentication.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &Authentication{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateCreate() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object creation. + return nil, r.ValidateAuthentication() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + return nil, r.ValidateAuthentication() +} + +// ValidateAuthentication validates the Authentication +func (r *Authentication) ValidateAuthentication() error { + var allErrs field.ErrorList + isOAuthDisabled := false + isMTLSMandatory := false + isMTLSDisabled := false + + if r.Spec.TargetRef.Name == "" { + allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("targetRef").Child("name"), "Name is required")) + } + if !(r.Spec.TargetRef.Kind == constants.KindAPI || r.Spec.TargetRef.Kind == constants.KindResource) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind, + "Invalid Kind is provided")) + } + + if r.Spec.Default != nil && r.Spec.Default.Disabled != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil { + isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled + isMTLSMandatory = strings.ToLower(r.Spec.Default.AuthTypes.MutualSSL.Required) == "mandatory" + isMTLSDisabled = r.Spec.Default.AuthTypes.MutualSSL.Disabled + if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("authTypes"), r.Spec.Default.AuthTypes, + "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) + } + } else if r.Spec.Override != nil && r.Spec.Override.Disabled != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil { + isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled + isMTLSMandatory = strings.ToLower(r.Spec.Override.AuthTypes.MutualSSL.Required) == "mandatory" + isMTLSDisabled = r.Spec.Override.AuthTypes.MutualSSL.Disabled + if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("authTypes"), r.Spec.Override.AuthTypes, + "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) + } + } + + if len(allErrs) > 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "dp.wso2.com", Kind: "Authentication"}, + r.Name, allErrs) + } + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateDelete() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object deletion. + return nil, nil +} diff --git a/common-go-libs/apis/dp/v1alpha1/webhook_suite_test.go b/common-go-libs/apis/dp/v1alpha1/webhook_suite_test.go index 5c56602ca..3dc05d4de 100644 --- a/common-go-libs/apis/dp/v1alpha1/webhook_suite_test.go +++ b/common-go-libs/apis/dp/v1alpha1/webhook_suite_test.go @@ -118,6 +118,9 @@ var _ = BeforeSuite(func() { err = (&BackendJWT{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&Authentication{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { diff --git a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml index 24c43accb..fcb15768b 100644 --- a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml @@ -67,6 +67,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details @@ -138,6 +202,70 @@ spec: type: object nullable: true type: array + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + required: + - required + type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication scheme details diff --git a/common-go-libs/config/webhook/manifests.yaml b/common-go-libs/config/webhook/manifests.yaml index c7026f4c8..7d86cb224 100644 --- a/common-go-libs/config/webhook/manifests.yaml +++ b/common-go-libs/config/webhook/manifests.yaml @@ -64,6 +64,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -210,6 +230,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml index 4d94ea9d8..229ef819d 100644 --- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml +++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml @@ -63,6 +63,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service + namespace: {{ .Release.Namespace }} + path: /mutate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml index 9a81bd9cd..0a2ca5d9c 100644 --- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml +++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml @@ -83,6 +83,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service + namespace: {{ .Release.Namespace }} + path: /validate-dp-wso2-com-v1alpha1-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None {{ if .Values.wso2.apk.dp.ratelimiter.enabled }} - admissionReviewVersions: - v1 diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal index bd9309bf3..3a0cd927e 100644 --- a/runtime/config-deployer-service/ballerina/APIClient.bal +++ b/runtime/config-deployer-service/ballerina/APIClient.bal @@ -340,9 +340,13 @@ public class APIClient { map createdEndpointMap, commons:Organization organization) returns error? { map authenticationMap = {}; model:AuthenticationExtensionType authTypes = {}; + boolean isOAuthDisabled = false; + boolean isMTLSMandatory = false; + boolean isMTLSDisabled = false; foreach AuthenticationRequest authentication in authentications { if authentication.authType == "OAuth2" { OAuth2Authentication oauth2Authentication = check authentication.cloneWithType(OAuth2Authentication); + isOAuthDisabled = !oauth2Authentication.enabled; authTypes.oauth2 = {header: oauth2Authentication.headerName, sendTokenToUpstream: oauth2Authentication.sendTokenToUpstream, disabled: !oauth2Authentication.enabled}; } else if authentication.authType == "APIKey" && authentication is APIKeyAuthentication { APIKeyAuthentication apiKeyAuthentication = check authentication.cloneWithType(APIKeyAuthentication); @@ -351,7 +355,14 @@ public class APIClient { authTypes.apiKey.push({'in: "Query", name: apiKeyAuthentication.queryParamName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); } else if authentication.authType == "mTLS" { MTLSAuthentication mtlsAuthentication = check authentication.cloneWithType(MTLSAuthentication); + isMTLSMandatory = mtlsAuthentication.required == "mandatory"; + isMTLSDisabled = !mtlsAuthentication.enabled; + if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { + log:printError("Invalid authtypes provided: one of mTLS or OAuth2 has to be enabled and mandatory"); + return e909019(); + } authTypes.mtls = {disabled: !mtlsAuthentication.enabled, configMapRefs: mtlsAuthentication.certificates, required: mtlsAuthentication.required}; + } } log:printDebug("Auth Types:" + authTypes.toString()); diff --git a/runtime/config-deployer-service/ballerina/Errors.bal b/runtime/config-deployer-service/ballerina/Errors.bal index 8c0857039..a76748613 100644 --- a/runtime/config-deployer-service/ballerina/Errors.bal +++ b/runtime/config-deployer-service/ballerina/Errors.bal @@ -175,11 +175,11 @@ public isolated function e909018(string msg) returns commons:APKError { } public isolated function e909019() returns commons:APKError { - return error commons:APKError("Invalid transport security schema", + return error commons:APKError("Invalid authtypes provided", code = 909018, - message = "Invalid transport security schema provided", + message = "Invalid authtypes provided", statusCode = 406, - description = "Invalid transport security schema provided" + description = "Invalid authtypes provided" ); } From 9da26f10129f055a1826f695c91da42a1950e789 Mon Sep 17 00:00:00 2001 From: sgayangi Date: Mon, 18 Dec 2023 09:14:09 +0530 Subject: [PATCH 11/15] Add functionality to disable mTLS --- .../api/proto/wso2/discovery/api/api.proto | 1 + .../internal/oasparser/config_generator.go | 1 + .../oasparser/model/adapter_internal_api.go | 11 ++ adapter/internal/operator/utils/utils.go | 4 +- .../api/wso2/discovery/api/api.pb.go | 91 ++++++++------- common-go-libs/apis/dp/v1alpha1/mutualSSL.go | 1 + .../apk/enforcer/commons/model/APIConfig.java | 18 +++ .../org/wso2/apk/enforcer/api/RestAPI.java | 3 +- .../wso2/apk/enforcer/discovery/api/Api.java | 65 +++++++++++ .../enforcer/discovery/api/ApiOrBuilder.java | 6 + .../apk/enforcer/discovery/api/ApiProto.java | 29 ++--- .../apk/enforcer/security/AuthFilter.java | 14 ++- .../ballerina/resources/apk-conf-schema.yaml | 10 +- .../ballerina/tests/resources/apk-schema.json | 109 +++++++++++++----- .../config-deployer/conf/apk-schema.json | 109 +++++++++++++----- runtime/runtime-ui/schema/apk-conf.yaml | 98 ++++++++-------- runtime/runtime-ui/schema/apk-schema.json | 102 ++++++++++++---- 17 files changed, 485 insertions(+), 187 deletions(-) diff --git a/adapter/api/proto/wso2/discovery/api/api.proto b/adapter/api/proto/wso2/discovery/api/api.proto index 887582b7b..8ce3fc9fd 100644 --- a/adapter/api/proto/wso2/discovery/api/api.proto +++ b/adapter/api/proto/wso2/discovery/api/api.proto @@ -51,6 +51,7 @@ message Api { repeated Certificate clientCertificates = 14; string mutualSSL = 15; bool applicationSecurity = 16; + bool transportSecurity = 17; /// string graphQLSchema = 22; repeated GraphqlComplexity graphqlComplexityInfo = 23; bool systemAPI = 24; diff --git a/adapter/internal/oasparser/config_generator.go b/adapter/internal/oasparser/config_generator.go index 050a73901..73ef25167 100644 --- a/adapter/internal/oasparser/config_generator.go +++ b/adapter/internal/oasparser/config_generator.go @@ -216,6 +216,7 @@ func GetEnforcerAPI(adapterInternalAPI model.AdapterInternalAPI, vhost string) * ClientCertificates: clientCertificates, MutualSSL: adapterInternalAPI.GetMutualSSL(), ApplicationSecurity: adapterInternalAPI.GetXWSO2ApplicationSecurity(), + TransportSecurity: !adapterInternalAPI.GetDisableMtls(), // GraphQLSchema: adapterInternalAPI.GraphQLSchema, // GraphqlComplexityInfo: adapterInternalAPI.GraphQLComplexities.Data.List, SystemAPI: adapterInternalAPI.IsSystemAPI, diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go index 1b44664a9..32a9068b3 100644 --- a/adapter/internal/oasparser/model/adapter_internal_api.go +++ b/adapter/internal/oasparser/model/adapter_internal_api.go @@ -58,6 +58,7 @@ type AdapterInternalAPI struct { xWso2AuthHeader string disableAuthentications bool disableScopes bool + disableMtls bool OrganizationID string IsPrototyped bool EndpointType string @@ -311,6 +312,11 @@ func (adapterInternalAPI *AdapterInternalAPI) GetDisableScopes() bool { return adapterInternalAPI.disableScopes } +// GetDisableMtls returns whether mTLS is disabled or not +func (swagger *AdapterInternalAPI) GetDisableMtls() bool { + return swagger.disableMtls +} + // GetID returns the Id of the API func (adapterInternalAPI *AdapterInternalAPI) GetID() string { return adapterInternalAPI.id @@ -403,6 +409,11 @@ func (swagger *AdapterInternalAPI) GetMutualSSL() string { return swagger.mutualSSL } +// SetDisableMtls returns whether mTLS is disabled or not +func (swagger *AdapterInternalAPI) SetDisableMtls(disableMtls bool) { + swagger.disableMtls = disableMtls +} + // SetXWSO2ApplicationSecurity sets the optional or mandatory application security func (adapterInternalAPI *AdapterInternalAPI) SetXWSO2ApplicationSecurity(applicationSecurity bool) { adapterInternalAPI.xWso2ApplicationSecurity = applicationSecurity diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go index dd3c8ea7a..376f22776 100644 --- a/adapter/internal/operator/utils/utils.go +++ b/adapter/internal/operator/utils/utils.go @@ -463,12 +463,12 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic var mutualSSL *dpv1alpha1.MutualSSLConfig if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil { mutualSSL = authentication.Spec.Default.AuthTypes.MutualSSL - } - if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil { + } else if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil { mutualSSL = authentication.Spec.Override.AuthTypes.MutualSSL } if mutualSSL != nil { resolvedCertificates := ResolveAllmTLSCertificates(ctx, mutualSSL, certificate, err, client, authentication.Namespace) + resolvedMutualSSL.Disabled = mutualSSL.Disabled resolvedMutualSSL.Required = authentication.Spec.Default.AuthTypes.MutualSSL.Required resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, resolvedCertificates...) } diff --git a/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go b/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go index c306038f6..a711b1c78 100644 --- a/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go +++ b/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go @@ -59,6 +59,7 @@ type Api struct { ClientCertificates []*Certificate `protobuf:"bytes,14,rep,name=clientCertificates,proto3" json:"clientCertificates,omitempty"` MutualSSL string `protobuf:"bytes,15,opt,name=mutualSSL,proto3" json:"mutualSSL,omitempty"` ApplicationSecurity bool `protobuf:"varint,16,opt,name=applicationSecurity,proto3" json:"applicationSecurity,omitempty"` + TransportSecurity bool `protobuf:"varint,17,opt,name=transportSecurity,proto3" json:"transportSecurity,omitempty"` /// string graphQLSchema = 22; GraphqlComplexityInfo []*GraphqlComplexity `protobuf:"bytes,23,rep,name=graphqlComplexityInfo,proto3" json:"graphqlComplexityInfo,omitempty"` SystemAPI bool `protobuf:"varint,24,opt,name=systemAPI,proto3" json:"systemAPI,omitempty"` @@ -214,6 +215,13 @@ func (x *Api) GetApplicationSecurity() bool { return false } +func (x *Api) GetTransportSecurity() bool { + if x != nil { + return x.TransportSecurity + } + return false +} + func (x *Api) GetGraphqlComplexityInfo() []*GraphqlComplexity { if x != nil { return x.GraphqlComplexityInfo @@ -290,7 +298,7 @@ var file_wso2_discovery_api_api_proto_rawDesc = []byte{ 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbf, + 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xed, 0x08, 0x0a, 0x03, 0x41, 0x70, 0x69, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, @@ -328,45 +336,48 @@ var file_wso2_discovery_api_api_proto_rawDesc = []byte{ 0x30, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x12, 0x5b, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x52, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, - 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, 0x18, 0x18, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, 0x12, 0x59, 0x0a, 0x13, - 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, - 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x73, 0x6f, 0x32, - 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x1a, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x1d, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, - 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, - 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x42, 0x70, 0x0a, 0x23, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, - 0x2e, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x77, 0x73, 0x6f, 0x32, - 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, - 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x79, 0x12, 0x2c, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x5b, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x78, 0x69, 0x74, 0x79, 0x52, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, 0x12, 0x59, 0x0a, 0x13, 0x62, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, + 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, + 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x12, 0x4c, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x73, 0x6f, + 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x42, 0x70, + 0x0a, 0x23, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, + 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, + 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go b/common-go-libs/apis/dp/v1alpha1/mutualSSL.go index 4becb1cd1..96485a159 100644 --- a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go +++ b/common-go-libs/apis/dp/v1alpha1/mutualSSL.go @@ -19,6 +19,7 @@ package v1alpha1 // MutualSSL defines the mutual SSL configurations for an API type MutualSSL struct { + Disabled bool Required string ClientCertificates []string } diff --git a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java index a3735286e..72aeddfc0 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java +++ b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java @@ -47,6 +47,7 @@ public class APIConfig { private boolean isMockedApi; private KeyStore trustStore; private String mutualSSL; + private boolean transportSecurity; private boolean applicationSecurity; private GraphQLSchemaDTO graphQLSchemaDTO; private JWTConfigurationDto jwtConfigurationDto; @@ -205,6 +206,15 @@ public String getMutualSSL() { return mutualSSL; } + /** + * Returns if transport security (mTLS) is enabled or disabled for the corresponding API. + * + * @return transportSecurity enabled + */ + public boolean isTransportSecurity() { + return transportSecurity; + } + /** * Returns the application security optionality for the corresponding API. * @@ -283,6 +293,8 @@ public static class Builder { private boolean subscriptionValidation; private JWTConfigurationDto jwtConfigurationDto; private String environment; + private boolean transportSecurity; + public Builder(String name) { this.name = name; } @@ -397,6 +409,11 @@ public Builder subscriptionValidation(boolean subscriptionValidation) { return this; } + public Builder transportSecurity(boolean transportSecurity) { + this.transportSecurity = transportSecurity; + return this; + } + public APIConfig build() { APIConfig apiConfig = new APIConfig(); apiConfig.name = this.name; @@ -415,6 +432,7 @@ public APIConfig build() { apiConfig.isMockedApi = this.isMockedApi; apiConfig.trustStore = this.trustStore; apiConfig.mutualSSL = this.mutualSSL; + apiConfig.transportSecurity = this.transportSecurity; apiConfig.applicationSecurity = this.applicationSecurity; apiConfig.graphQLSchemaDTO = this.graphQLSchemaDTO; apiConfig.systemAPI = this.systemAPI; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java index 6071b518c..069a2ea35 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java @@ -129,7 +129,8 @@ public String init(Api api) { .mutualSSL(mutualSSL).systemAPI(api.getSystemAPI()) .applicationSecurity(applicationSecurity).jwtConfigurationDto(jwtConfigurationDto) .apiDefinition(apiDefinition).environment(api.getEnvironment()) - .subscriptionValidation(api.getSubscriptionValidation()).build(); + .subscriptionValidation(api.getSubscriptionValidation()).transportSecurity(api.getTransportSecurity()) + .build(); initFilters(); return basePath; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java index 451fd9277..d0614f392 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java @@ -169,6 +169,11 @@ private Api( applicationSecurity_ = input.readBool(); break; } + case 136: { + + transportSecurity_ = input.readBool(); + break; + } case 186: { if (!((mutable_bitField0_ & 0x00000004) != 0)) { graphqlComplexityInfo_ = new java.util.ArrayList(); @@ -829,6 +834,17 @@ public boolean getApplicationSecurity() { return applicationSecurity_; } + public static final int TRANSPORTSECURITY_FIELD_NUMBER = 17; + private boolean transportSecurity_; + /** + * bool transportSecurity = 17; + * @return The transportSecurity. + */ + @java.lang.Override + public boolean getTransportSecurity() { + return transportSecurity_; + } + public static final int GRAPHQLCOMPLEXITYINFO_FIELD_NUMBER = 23; private java.util.List graphqlComplexityInfo_; /** @@ -1114,6 +1130,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (applicationSecurity_ != false) { output.writeBool(16, applicationSecurity_); } + if (transportSecurity_ != false) { + output.writeBool(17, transportSecurity_); + } for (int i = 0; i < graphqlComplexityInfo_.size(); i++) { output.writeMessage(23, graphqlComplexityInfo_.get(i)); } @@ -1200,6 +1219,10 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeBoolSize(16, applicationSecurity_); } + if (transportSecurity_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(17, transportSecurity_); + } for (int i = 0; i < graphqlComplexityInfo_.size(); i++) { size += com.google.protobuf.CodedOutputStream .computeMessageSize(23, graphqlComplexityInfo_.get(i)); @@ -1278,6 +1301,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getMutualSSL())) return false; if (getApplicationSecurity() != other.getApplicationSecurity()) return false; + if (getTransportSecurity() + != other.getTransportSecurity()) return false; if (!getGraphqlComplexityInfoList() .equals(other.getGraphqlComplexityInfoList())) return false; if (getSystemAPI() @@ -1350,6 +1375,9 @@ public int hashCode() { hash = (37 * hash) + APPLICATIONSECURITY_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( getApplicationSecurity()); + hash = (37 * hash) + TRANSPORTSECURITY_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getTransportSecurity()); if (getGraphqlComplexityInfoCount() > 0) { hash = (37 * hash) + GRAPHQLCOMPLEXITYINFO_FIELD_NUMBER; hash = (53 * hash) + getGraphqlComplexityInfoList().hashCode(); @@ -1557,6 +1585,8 @@ public Builder clear() { applicationSecurity_ = false; + transportSecurity_ = false; + if (graphqlComplexityInfoBuilder_ == null) { graphqlComplexityInfo_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000004); @@ -1648,6 +1678,7 @@ public org.wso2.apk.enforcer.discovery.api.Api buildPartial() { } result.mutualSSL_ = mutualSSL_; result.applicationSecurity_ = applicationSecurity_; + result.transportSecurity_ = transportSecurity_; if (graphqlComplexityInfoBuilder_ == null) { if (((bitField0_ & 0x00000004) != 0)) { graphqlComplexityInfo_ = java.util.Collections.unmodifiableList(graphqlComplexityInfo_); @@ -1833,6 +1864,9 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { if (other.getApplicationSecurity() != false) { setApplicationSecurity(other.getApplicationSecurity()); } + if (other.getTransportSecurity() != false) { + setTransportSecurity(other.getTransportSecurity()); + } if (graphqlComplexityInfoBuilder_ == null) { if (!other.graphqlComplexityInfo_.isEmpty()) { if (graphqlComplexityInfo_.isEmpty()) { @@ -3415,6 +3449,37 @@ public Builder clearApplicationSecurity() { return this; } + private boolean transportSecurity_ ; + /** + * bool transportSecurity = 17; + * @return The transportSecurity. + */ + @java.lang.Override + public boolean getTransportSecurity() { + return transportSecurity_; + } + /** + * bool transportSecurity = 17; + * @param value The transportSecurity to set. + * @return This builder for chaining. + */ + public Builder setTransportSecurity(boolean value) { + + transportSecurity_ = value; + onChanged(); + return this; + } + /** + * bool transportSecurity = 17; + * @return This builder for chaining. + */ + public Builder clearTransportSecurity() { + + transportSecurity_ = false; + onChanged(); + return this; + } + private java.util.List graphqlComplexityInfo_ = java.util.Collections.emptyList(); private void ensureGraphqlComplexityInfoIsMutable() { diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java index 68a84404c..9a519528d 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java @@ -225,6 +225,12 @@ org.wso2.apk.enforcer.discovery.api.CertificateOrBuilder getClientCertificatesOr */ boolean getApplicationSecurity(); + /** + * bool transportSecurity = 17; + * @return The transportSecurity. + */ + boolean getTransportSecurity(); + /** *
    */ string graphQLSchema = 22;
diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java
index 9350f8db7..76ecc750b 100644
--- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java
+++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java
@@ -35,7 +35,7 @@ public static void registerAllExtensions(
       "nfo.proto\032)wso2/discovery/api/endpoint_c" +
       "luster.proto\032&wso2/discovery/api/securit" +
       "y_info.proto\032 wso2/discovery/api/graphql" +
-      ".proto\"\355\005\n\003Api\022\n\n\002id\030\001 \001(\t\022\r\n\005title\030\002 \001(" +
+      ".proto\"\210\006\n\003Api\022\n\n\002id\030\001 \001(\t\022\r\n\005title\030\002 \001(" +
       "\t\022\017\n\007version\030\003 \001(\t\022\017\n\007apiType\030\004 \001(\t\022\036\n\026d" +
       "isableAuthentications\030\005 \001(\010\022\025\n\rdisableSc" +
       "opes\030\006 \001(\010\022\017\n\007envType\030\007 \001(\t\022/\n\tresources" +
@@ -45,18 +45,19 @@ public static void registerAllExtensions(
       "zationId\030\r \001(\t\022;\n\022clientCertificates\030\016 \003" +
       "(\0132\037.wso2.discovery.api.Certificate\022\021\n\tm" +
       "utualSSL\030\017 \001(\t\022\033\n\023applicationSecurity\030\020 " +
-      "\001(\010\022D\n\025graphqlComplexityInfo\030\027 \003(\0132%.wso" +
-      "2.discovery.api.GraphqlComplexity\022\021\n\tsys" +
-      "temAPI\030\030 \001(\010\022D\n\023backendJWTTokenInfo\030\031 \001(" +
-      "\0132\'.wso2.discovery.api.BackendJWTTokenIn" +
-      "fo\022\031\n\021apiDefinitionFile\030\032 \001(\014\022\023\n\013environ" +
-      "ment\030\033 \001(\t\022\036\n\026subscriptionValidation\030\034 \001" +
-      "(\010\0226\n\tendpoints\030\035 \001(\0132#.wso2.discovery.a" +
-      "pi.EndpointCluster\022:\n\020endpointSecurity\030\036" +
-      " \003(\0132 .wso2.discovery.api.SecurityInfoBp" +
-      "\n#org.wso2.apk.enforcer.discovery.apiB\010A" +
-      "piProtoP\001Z=github.com/envoyproxy/go-cont" +
-      "rol-plane/wso2/discovery/api;apib\006proto3"
+      "\001(\010\022\031\n\021transportSecurity\030\021 \001(\010\022D\n\025graphq" +
+      "lComplexityInfo\030\027 \003(\0132%.wso2.discovery.a" +
+      "pi.GraphqlComplexity\022\021\n\tsystemAPI\030\030 \001(\010\022" +
+      "D\n\023backendJWTTokenInfo\030\031 \001(\0132\'.wso2.disc" +
+      "overy.api.BackendJWTTokenInfo\022\031\n\021apiDefi" +
+      "nitionFile\030\032 \001(\014\022\023\n\013environment\030\033 \001(\t\022\036\n" +
+      "\026subscriptionValidation\030\034 \001(\010\0226\n\tendpoin" +
+      "ts\030\035 \001(\0132#.wso2.discovery.api.EndpointCl" +
+      "uster\022:\n\020endpointSecurity\030\036 \003(\0132 .wso2.d" +
+      "iscovery.api.SecurityInfoBp\n#org.wso2.ap" +
+      "k.enforcer.discovery.apiB\010ApiProtoP\001Z=gi" +
+      "thub.com/envoyproxy/go-control-plane/wso" +
+      "2/discovery/api;apib\006proto3"
     };
     descriptor = com.google.protobuf.Descriptors.FileDescriptor
       .internalBuildGeneratedFileFrom(descriptorData,
@@ -73,7 +74,7 @@ public static void registerAllExtensions(
     internal_static_wso2_discovery_api_Api_fieldAccessorTable = new
       com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
         internal_static_wso2_discovery_api_Api_descriptor,
-        new java.lang.String[] { "Id", "Title", "Version", "ApiType", "DisableAuthentications", "DisableScopes", "EnvType", "Resources", "BasePath", "Tier", "ApiLifeCycleState", "Vhost", "OrganizationId", "ClientCertificates", "MutualSSL", "ApplicationSecurity", "GraphqlComplexityInfo", "SystemAPI", "BackendJWTTokenInfo", "ApiDefinitionFile", "Environment", "SubscriptionValidation", "Endpoints", "EndpointSecurity", });
+        new java.lang.String[] { "Id", "Title", "Version", "ApiType", "DisableAuthentications", "DisableScopes", "EnvType", "Resources", "BasePath", "Tier", "ApiLifeCycleState", "Vhost", "OrganizationId", "ClientCertificates", "MutualSSL", "ApplicationSecurity", "TransportSecurity", "GraphqlComplexityInfo", "SystemAPI", "BackendJWTTokenInfo", "ApiDefinitionFile", "Environment", "SubscriptionValidation", "Endpoints", "EndpointSecurity", });
     org.wso2.apk.enforcer.discovery.api.ResourceProto.getDescriptor();
     org.wso2.apk.enforcer.discovery.api.CertificateProto.getDescriptor();
     org.wso2.apk.enforcer.discovery.api.BackendJWTTokenInfoProto.getDescriptor();
diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java
index 0715006e4..8398b6db4 100644
--- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java
+++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java
@@ -72,11 +72,15 @@ private void initializeAuthenticators(APIConfig apiConfig) {
         isOAuthBasicAuthMandatory = apiConfig.getApplicationSecurity();
 
         if (!Objects.isNull(apiConfig.getMutualSSL())) {
-            if (apiConfig.getMutualSSL().equalsIgnoreCase(APIConstants.Optionality.MANDATORY)) {
-                isMutualSSLProtected = true;
-                isMutualSSLMandatory = true;
-            } else if (apiConfig.getMutualSSL().equalsIgnoreCase(APIConstants.Optionality.OPTIONAL)) {
-                isMutualSSLProtected = true;
+            if (apiConfig.isTransportSecurity()) {
+                if (apiConfig.getMutualSSL().equalsIgnoreCase(APIConstants.Optionality.MANDATORY)) {
+                    isMutualSSLProtected = true;
+                    isMutualSSLMandatory = true;
+                } else if (apiConfig.getMutualSSL().equalsIgnoreCase(APIConstants.Optionality.OPTIONAL)) {
+                    isMutualSSLProtected = true;
+                }
+            } else {
+                isMutualSSLProtected = false;
             }
         }
 
diff --git a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
index 43a131efd..552cebd5f 100644
--- a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
+++ b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
@@ -155,8 +155,14 @@ components:
                 - optional
             certificates:
               type: array
-              example: []
-              default: []
+              description: The names and keys of the secrets containing the mTLS certificates of that API
+              items:
+                type: object
+                properties:
+                  name:
+                    type: string
+                  key:
+                    type: string
           additionalProperties: false
     CORSConfiguration:
       type: object
diff --git a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
index 53b120c43..47846c036 100644
--- a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
+++ b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
@@ -43,7 +43,7 @@
       "type": "boolean",
       "description": "Is this the default version of the API"
     },
-    "subscriptionValidation" : {
+    "subscriptionValidation": {
       "type": "boolean",
       "description": "Is subscription validation enabled for the API"
     },
@@ -73,7 +73,17 @@
     "authentication": {
       "type": "array",
       "items": {
-        "$ref": "#/schemas/Authentication"
+        "oneOf": [
+          {
+            "$ref": "#/schemas/OAuth2Authentication"
+          },
+          {
+            "$ref": "#/schemas/MTLSAuthentication"
+          },
+          {
+            "$ref": "#/schemas/APIKeyAuthentication"
+          }
+        ]
       }
     },
     "additionalProperties": {
@@ -98,50 +108,58 @@
   },
   "additionalProperties": false,
   "schemas": {
-    "Authentication": {
+    "OAuth2Authentication": {
       "type": "object",
       "properties": {
         "authType": {
           "type": "string",
-          "example": "OAuth2",
-          "description": "The type of authentication to be used, e.g., OAuth2, etc."
+          "enum": [
+            "OAuth2"
+          ]
         },
         "sendTokenToUpstream": {
           "type": "boolean",
-          "default": false,
-          "description": "Specifies whether to send the authentication token to the upstream service."
+          "default": false
         },
         "enabled": {
-          "type": "boolean",
-          "example": true,
-          "description": "Specifies whether authentication is enabled for the API."
+          "type": "boolean"
         },
         "headerName": {
-          "type": "string",
-          "example": "Authorization",
-          "description": "The name of the header field used to send the authentication token."
+          "type": "string"
         },
         "queryParamName": {
-          "type": "string",
-          "example": "apikey",
-          "description": "The name of the query parameter used to send the authentication token."
+          "type": "string"
         },
         "headerEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent in the header."
+          "type": "boolean"
         },
         "queryParamEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent as a query parameter."
+          "type": "boolean"
+        }
+      },
+      "additionalProperties": false
+    },
+    "MTLSAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "enum": [
+            "mTLS"
+          ]
         },
         "required": {
           "type": "string",
-          "example": "mandatory",
-          "description": "Specifies whether mTLS is mandatory or optional"
+          "enum": [
+            "mandatory",
+            "optional"
+          ]
+        },
+        "enabled": {
+          "type": "boolean"
         },
         "certificates": {
           "type": "array",
-          "description": "The names and keys of the config maps containing the mTLS certificates of that API",
           "items": {
             "type": "object",
             "properties": {
@@ -152,10 +170,49 @@
                 "type": "string"
               }
             }
-          },
-          "additionalProperties": false
+          }
         }
-      }
+      },
+      "additionalProperties": false
+    },
+    "APIKeyAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "example": "APIKey",
+          "enum": [
+            "APIKey"
+          ],
+          "description": "The type of authentication to be used, e.g., APIKey, etc."
+        },
+        "enabled": {
+          "type": "boolean"
+        },
+        "sendTokenToUpstream": {
+          "type": "boolean",
+          "default": false
+        },
+        "headerName": {
+          "type": "string",
+          "example": "Authorization",
+          "default": "apikey"
+        },
+        "queryParamName": {
+          "type": "string",
+          "example": "apikey",
+          "default": "apikey"
+        },
+        "headerEnable": {
+          "type": "boolean",
+          "default": true
+        },
+        "queryParamEnable": {
+          "type": "boolean",
+          "default": true
+        }
+      },
+      "additionalProperties": false
     },
     "CORSConfiguration": {
       "type": "object",
diff --git a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
index 6f036f508..47846c036 100644
--- a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
+++ b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
@@ -13,7 +13,7 @@
     },
     "basePath": {
       "type": "string",
-      "title": "basePath of the API",
+      "title": "Base Path of the API",
       "maxLength": 256,
       "minLength": 1
     },
@@ -73,7 +73,17 @@
     "authentication": {
       "type": "array",
       "items": {
-        "$ref": "#/schemas/Authentication"
+        "oneOf": [
+          {
+            "$ref": "#/schemas/OAuth2Authentication"
+          },
+          {
+            "$ref": "#/schemas/MTLSAuthentication"
+          },
+          {
+            "$ref": "#/schemas/APIKeyAuthentication"
+          }
+        ]
       }
     },
     "additionalProperties": {
@@ -98,50 +108,58 @@
   },
   "additionalProperties": false,
   "schemas": {
-    "Authentication": {
+    "OAuth2Authentication": {
       "type": "object",
       "properties": {
         "authType": {
           "type": "string",
-          "example": "OAuth2",
-          "description": "The type of authentication to be used, e.g., OAuth2, etc."
+          "enum": [
+            "OAuth2"
+          ]
         },
         "sendTokenToUpstream": {
           "type": "boolean",
-          "default": false,
-          "description": "Specifies whether to send the authentication token to the upstream service."
+          "default": false
         },
         "enabled": {
-          "type": "boolean",
-          "example": true,
-          "description": "Specifies whether authentication is enabled for the API."
+          "type": "boolean"
         },
         "headerName": {
-          "type": "string",
-          "example": "Authorization",
-          "description": "The name of the header field used to send the authentication token."
+          "type": "string"
         },
         "queryParamName": {
-          "type": "string",
-          "example": "apikey",
-          "description": "The name of the query parameter used to send the authentication token."
+          "type": "string"
         },
         "headerEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent in the header."
+          "type": "boolean"
         },
         "queryParamEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent as a query parameter."
+          "type": "boolean"
+        }
+      },
+      "additionalProperties": false
+    },
+    "MTLSAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "enum": [
+            "mTLS"
+          ]
         },
         "required": {
           "type": "string",
-          "example": "mandatory",
-          "description": "Specifies whether mTLS is mandatory or optional"
+          "enum": [
+            "mandatory",
+            "optional"
+          ]
+        },
+        "enabled": {
+          "type": "boolean"
         },
         "certificates": {
           "type": "array",
-          "description": "The names and keys of the config maps containing the mTLS certificates of that API",
           "items": {
             "type": "object",
             "properties": {
@@ -152,10 +170,49 @@
                 "type": "string"
               }
             }
-          },
-          "additionalProperties": false
+          }
         }
-      }
+      },
+      "additionalProperties": false
+    },
+    "APIKeyAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "example": "APIKey",
+          "enum": [
+            "APIKey"
+          ],
+          "description": "The type of authentication to be used, e.g., APIKey, etc."
+        },
+        "enabled": {
+          "type": "boolean"
+        },
+        "sendTokenToUpstream": {
+          "type": "boolean",
+          "default": false
+        },
+        "headerName": {
+          "type": "string",
+          "example": "Authorization",
+          "default": "apikey"
+        },
+        "queryParamName": {
+          "type": "string",
+          "example": "apikey",
+          "default": "apikey"
+        },
+        "headerEnable": {
+          "type": "boolean",
+          "default": true
+        },
+        "queryParamEnable": {
+          "type": "boolean",
+          "default": true
+        }
+      },
+      "additionalProperties": false
     },
     "CORSConfiguration": {
       "type": "object",
diff --git a/runtime/runtime-ui/schema/apk-conf.yaml b/runtime/runtime-ui/schema/apk-conf.yaml
index 23e98266b..9400caacc 100644
--- a/runtime/runtime-ui/schema/apk-conf.yaml
+++ b/runtime/runtime-ui/schema/apk-conf.yaml
@@ -57,7 +57,10 @@ properties:
   authentication:
     type: array
     items:
-      "$ref": "#/schemas/Authentication"
+      oneOf:
+        - $ref: "#/schemas/OAuth2Authentication"
+        - $ref: "#/schemas/MTLSAuthentication"
+        - $ref: "#/schemas/APIKeyAuthentication"
   additionalProperties:
     type: array
     description: Map of custom properties of API
@@ -73,45 +76,48 @@ properties:
     description: Cross-Origin Resource Sharing (CORS) configuration for the API.
 additionalProperties: false
 schemas:
-  Authentication:
+  OAuth2Authentication:
     type: object
     properties:
       authType:
         type: string
-        example: OAuth2
+        enum: [OAuth2]
         description: The type of authentication to be used, e.g., OAuth2, etc.
       sendTokenToUpstream:
         type: boolean
         default: false
-        description:
-          Specifies whether to send the authentication token to the upstream
-          service.
+        description: Specifies whether to send the authentication token to the upstream service.
       enabled:
         type: boolean
         example: true
-        description: Specifies whether authentication is enabled for the API.
+        description: Specifies whether OAuth2 authentication is enabled for the API.
       headerName:
         type: string
         example: Authorization
-        description:
-          The name of the header field used to send the authentication
-          token.
+        description: The name of the header field used to send the authentication token.
       queryParamName:
         type: string
         example: apikey
-        description:
-          The name of the query parameter used to send the authentication
-          token.
+        description: The name of the query parameter used to send the authentication token.
       headerEnable:
         type: boolean
-        description:
-          Specifies whether the authentication token can be sent in the
-          header.
+        description: Specifies whether the authentication token can be sent in the header.
       queryParamEnable:
         type: boolean
-        description:
-          Specifies whether the authentication token can be sent as a query
-          parameter.
+        description: Specifies whether the authentication token can be sent as a query parameter.
+    additionalProperties: false
+  MTLSAuthentication:
+    type: object
+    properties:
+      authType:
+        type: string
+        example: mTLS
+        enum: [mTLS]
+        description: The type of authentication to be used, e.g., mTLS, etc.
+      enabled:
+        type: boolean
+        example: true
+        description: Specifies whether mTLS authentication is enabled for the API.
       required:
         type: string
         enum:
@@ -129,34 +135,32 @@ schemas:
             key:
               type: string
     additionalProperties: false
-  mTLS:
-    type: object
-    properties:
-      required:
-        type: string
-        example: mandatory
-        description: Specifies whether mTLS is mandatory or optional.
-      secrets:
-        type: array
-        description: The names and keys of the secrets containing the mTLS certificates of that API.
-        items:
-          type: object
-          properties:
-            secretName:
-              type: string
-            secretKey:
-              type: string
-      configMaps:
-        type: array
-        description: The names and keys of the secrets containing the mTLS certificates of that API.
-        items:
-          type: object
-          properties:
-            configMapName:
-              type: string
-            configMapKey:
-              type: string
-    additionalProperties: false
+  APIKeyAuthentication:
+    - type: object
+      properties:
+        authType:
+          type: string
+          example: APIKey
+          enum: [APIKey]
+          description: The type of authentication to be used, e.g., APIKey, etc.
+        sendTokenToUpstream:
+          type: boolean
+          default: false
+        headerName:
+          type: string
+          example: Authorization
+          default: apikey
+        queryParamName:
+          type: string
+          example: apikey
+          default: apikey
+        headerEnable:
+          type: boolean
+          default: true
+        queryParamEnable:
+          type: boolean
+          default: true
+      additionalProperties: false
   CORSConfiguration:
     type: object
     description: Cross-Origin Resource Sharing (CORS) configuration for the API.
diff --git a/runtime/runtime-ui/schema/apk-schema.json b/runtime/runtime-ui/schema/apk-schema.json
index 56d205072..47846c036 100644
--- a/runtime/runtime-ui/schema/apk-schema.json
+++ b/runtime/runtime-ui/schema/apk-schema.json
@@ -73,7 +73,17 @@
     "authentication": {
       "type": "array",
       "items": {
-        "$ref": "#/schemas/Authentication"
+        "oneOf": [
+          {
+            "$ref": "#/schemas/OAuth2Authentication"
+          },
+          {
+            "$ref": "#/schemas/MTLSAuthentication"
+          },
+          {
+            "$ref": "#/schemas/APIKeyAuthentication"
+          }
+        ]
       }
     },
     "additionalProperties": {
@@ -98,60 +108,65 @@
   },
   "additionalProperties": false,
   "schemas": {
-    "Authentication": {
+    "OAuth2Authentication": {
       "type": "object",
       "properties": {
         "authType": {
           "type": "string",
-          "example": "OAuth2",
-          "description": "The type of authentication to be used, e.g., OAuth2, etc."
+          "enum": [
+            "OAuth2"
+          ]
         },
         "sendTokenToUpstream": {
           "type": "boolean",
-          "default": false,
-          "description": "Specifies whether to send the authentication token to the upstream service."
+          "default": false
         },
         "enabled": {
-          "type": "boolean",
-          "example": true,
-          "description": "Specifies whether authentication is enabled for the API."
+          "type": "boolean"
         },
         "headerName": {
-          "type": "string",
-          "example": "Authorization",
-          "description": "The name of the header field used to send the authentication token."
+          "type": "string"
         },
         "queryParamName": {
-          "type": "string",
-          "example": "apikey",
-          "description": "The name of the query parameter used to send the authentication token."
+          "type": "string"
         },
         "headerEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent in the header."
+          "type": "boolean"
         },
         "queryParamEnable": {
-          "type": "boolean",
-          "description": "Specifies whether the authentication token can be sent as a query parameter."
+          "type": "boolean"
+        }
+      },
+      "additionalProperties": false
+    },
+    "MTLSAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "enum": [
+            "mTLS"
+          ]
         },
         "required": {
           "type": "string",
           "enum": [
             "mandatory",
             "optional"
-          ],
-          "description": "Specifies whether mTLS is mandatory or optional"
+          ]
+        },
+        "enabled": {
+          "type": "boolean"
         },
         "certificates": {
           "type": "array",
-          "description": "The names and keys of the secrets containing the mTLS certificates of that API",
           "items": {
             "type": "object",
             "properties": {
-              "secretName": {
+              "name": {
                 "type": "string"
               },
-              "secretKey": {
+              "key": {
                 "type": "string"
               }
             }
@@ -160,6 +175,45 @@
       },
       "additionalProperties": false
     },
+    "APIKeyAuthentication": {
+      "type": "object",
+      "properties": {
+        "authType": {
+          "type": "string",
+          "example": "APIKey",
+          "enum": [
+            "APIKey"
+          ],
+          "description": "The type of authentication to be used, e.g., APIKey, etc."
+        },
+        "enabled": {
+          "type": "boolean"
+        },
+        "sendTokenToUpstream": {
+          "type": "boolean",
+          "default": false
+        },
+        "headerName": {
+          "type": "string",
+          "example": "Authorization",
+          "default": "apikey"
+        },
+        "queryParamName": {
+          "type": "string",
+          "example": "apikey",
+          "default": "apikey"
+        },
+        "headerEnable": {
+          "type": "boolean",
+          "default": true
+        },
+        "queryParamEnable": {
+          "type": "boolean",
+          "default": true
+        }
+      },
+      "additionalProperties": false
+    },
     "CORSConfiguration": {
       "type": "object",
       "description": "Cross-Origin Resource Sharing (CORS) configuration for the API.",

From c73d361a51ca1ab6285509511add88f2f6a58dd7 Mon Sep 17 00:00:00 2001
From: sgayangi 
Date: Thu, 21 Dec 2023 15:25:20 +0530
Subject: [PATCH 12/15] Add cucumber tests for mTLS

---
 .../jwt/UnsecuredAPIAuthenticator.java        |   2 +-
 .../integration/api/MTLSClientCertSteps.java  |  83 ++++++++
 .../mtls_disabled_oauth2_disabled.apk-conf    |  35 ++++
 .../mtls_disabled_oauth2_enabled.apk-conf     |  33 ++++
 .../mtls_mandatory_oauth2_disabled.apk-conf   |  34 ++++
 .../mtls_mandatory_oauth2_enabled.apk-conf    |  32 +++
 .../apk-confs/mtls_multiple_certs.apk-conf    |  34 ++++
 .../mtls_optional_oauth2_disabled.apk-conf    |  34 ++++
 .../mtls_optional_oauth2_enabled.apk-conf     |  32 +++
 .../src/test/resources/tests/api/MTLS.feature | 182 ++++++++++++++++++
 10 files changed, 500 insertions(+), 1 deletion(-)
 create mode 100644 test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf
 create mode 100644 test/cucumber-tests/src/test/resources/tests/api/MTLS.feature

diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/UnsecuredAPIAuthenticator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/UnsecuredAPIAuthenticator.java
index 48d1d481f..5904dcaee 100644
--- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/UnsecuredAPIAuthenticator.java
+++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/UnsecuredAPIAuthenticator.java
@@ -47,7 +47,7 @@ public boolean canAuthenticate(RequestContext requestContext) {
         // Retrieve the disable security value. If security is disabled for all matching resources,
         // then you can proceed directly with the authentication.
         for (ResourceConfig resourceConfig : requestContext.getMatchedResourcePaths()) {
-            if (!resourceConfig.getAuthenticationConfig().isDisabled()) {
+            if (!resourceConfig.getAuthenticationConfig().isDisabled() || requestContext.getMatchedAPI().isTransportSecurity()) {
                 return false;
             }
         }
diff --git a/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
new file mode 100644
index 000000000..db0cf7fbf
--- /dev/null
+++ b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2023, WSO2 LLC (http://www.wso2.com).
+ *
+ * WSO2 LLC licenses this file to you 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 org.wso2.apk.integration.api;
+
+import org.apache.http.HttpResponse;
+import org.wso2.apk.integration.utils.Constants;
+import org.wso2.apk.integration.utils.Utils;
+import org.wso2.apk.integration.utils.clients.SimpleHTTPClient;
+
+import io.cucumber.java.Before;
+import io.cucumber.java.en.Then;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class contains the common step definitions.
+ */
+public class MTLSClientCertSteps {
+
+        private final SharedContext sharedContext;
+        private SimpleHTTPClient httpClient;
+
+        public MTLSClientCertSteps(SharedContext sharedContext) {
+
+                this.sharedContext = sharedContext;
+        }
+
+        @Before
+        public void setup() throws Exception {
+
+                httpClient = sharedContext.getHttpClient();
+        }
+
+        @Then("I have a valid subscription with a valid client certificate")
+        public void getValidClientCertificateForMTLS() throws Exception {
+
+                Map headers = new HashMap<>();
+                headers.put(Constants.REQUEST_HEADERS.HOST, Constants.DEFAULT_IDP_HOST);
+                headers.put(Constants.REQUEST_HEADERS.AUTHORIZATION,
+                                "Basic NDVmMWM1YzgtYTkyZS0xMWVkLWFmYTEtMDI0MmFjMTIwMDAyOjRmYmQ2MmVjLWE5MmUtMTFlZC1hZmExLTAyNDJhYzEyMDAwMg==");
+
+                HttpResponse httpResponse = httpClient.doPost(Utils.getTokenEndpointURL(), headers,
+                                "grant_type=client_credentials&scope=" + Constants.API_CREATE_SCOPE,
+                                Constants.CONTENT_TYPES.APPLICATION_X_WWW_FORM_URLENCODED);
+                sharedContext.setAccessToken(Utils.extractToken(httpResponse));
+                sharedContext.addStoreValue("accessToken", sharedContext.getAccessToken());
+                sharedContext.addStoreValue("clientCertificate",
+                                "-----BEGIN CERTIFICATE-----MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28yMQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0yNTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9ivVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwLm7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQQxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6UhxZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McTCOKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBGzUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinBYlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=-----END CERTIFICATE-----");
+        }
+
+        @Then("I have a valid subscription with an invalid client certificate")
+        public void getInvalidClientCertificateForMTLS() throws Exception {
+
+                Map headers = new HashMap<>();
+                headers.put(Constants.REQUEST_HEADERS.HOST, Constants.DEFAULT_IDP_HOST);
+                headers.put(Constants.REQUEST_HEADERS.AUTHORIZATION,
+                                "Basic NDVmMWM1YzgtYTkyZS0xMWVkLWFmYTEtMDI0MmFjMTIwMDAyOjRmYmQ2MmVjLWE5MmUtMTFlZC1hZmExLTAyNDJhYzEyMDAwMg==");
+
+                HttpResponse httpResponse = httpClient.doPost(Utils.getTokenEndpointURL(), headers,
+                                "grant_type=client_credentials&scope=" + Constants.API_CREATE_SCOPE,
+                                Constants.CONTENT_TYPES.APPLICATION_X_WWW_FORM_URLENCODED);
+                sharedContext.setAccessToken(Utils.extractToken(httpResponse));
+                sharedContext.addStoreValue("accessToken", sharedContext.getAccessToken());
+                sharedContext.addStoreValue("clientCertificate",
+                                "-----BEGIN CERTIFICATE-----MIIDJDCfeXw==-----END CERTIFICATE-----");
+        }
+}
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf
new file mode 100644
index 000000000..28babf72f
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf
@@ -0,0 +1,35 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-disabled-oauth2-disabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://webhook.site/1e73a7f6-6187-46ff-aac9-f060d7460c93"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: OAuth2
+    enabled: false
+  - authType: mTLS
+    required: optional
+    enabled: false
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf
new file mode 100644
index 000000000..88602c950
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf
@@ -0,0 +1,33 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-disabled-oauth2-enabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://run.mocky.io/v3/0c5173b2-9d99-459c-946b-b6b67c7f0139"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: mTLS
+    required: optional
+    enabled: false
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf
new file mode 100644
index 000000000..05b6887fc
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf
@@ -0,0 +1,34 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-mandatory-oauth2-disabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://run.mocky.io/v3/0c5173b2-9d99-459c-946b-b6b67c7f0139"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: OAuth2
+    enabled: false
+  - authType: mTLS
+    required: mandatory
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf
new file mode 100644
index 000000000..c91fcc890
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf
@@ -0,0 +1,32 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-mandatory-oauth2-enabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://run.mocky.io/v3/0c5173b2-9d99-459c-946b-b6b67c7f0139"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: mTLS
+    required: mandatory
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf
new file mode 100644
index 000000000..3429c24b9
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf
@@ -0,0 +1,34 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-multiple-certs"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://run.mocky.io/v3/0c5173b2-9d99-459c-946b-b6b67c7f0139"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: mTLS
+    required: mandatory
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
+      - name: mtls-test-configmap2
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf
new file mode 100644
index 000000000..da984143c
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf
@@ -0,0 +1,34 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-optional-oauth2-disabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://webhook.site/1e73a7f6-6187-46ff-aac9-f060d7460c93"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: OAuth2
+    enabled: false
+  - authType: mTLS
+    required: optional
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf
new file mode 100644
index 000000000..e30922bdb
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf
@@ -0,0 +1,32 @@
+name: "EmployeeServiceAPI"
+basePath: "/mtls"
+version: "3.14"
+type: "REST"
+id: "mtls-optional-oauth2-enabled"
+defaultVersion: false
+endpointConfigurations:
+  production:
+    endpoint: "https://run.mocky.io/v3/0c5173b2-9d99-459c-946b-b6b67c7f0139"
+operations:
+  - target: "/employee"
+    verb: "GET"
+    secured: true
+    scopes: []
+  - target: "/employee"
+    verb: "POST"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "PUT"
+    secured: true
+    scopes: []
+  - target: "/employee/{employeeId}"
+    verb: "DELETE"
+    secured: true
+    scopes: []
+authentication:
+  - authType: mTLS
+    required: optional
+    certificates:
+      - name: mtls-test-configmap
+        key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature b/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature
new file mode 100644
index 000000000..5e802821a
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature
@@ -0,0 +1,182 @@
+Feature: Test mTLS between client and gateway with client certificate sent in header
+    Scenario: Test mandatory mTLS and enabled OAuth2 with a valid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test mandatory mTLS and enabled OAuth2 with an invalid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with an invalid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 401
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test mandatory mTLS and enabled OAuth2 without a client certificate in header
+        Given The system is ready
+        And I have a valid subscription
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization | bearer ${accessToken} |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 401
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test mandatory mTLS and disabled OAuth2 with a valid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
+        Then the response status code should be 202
+
+    Scenario: Test mandatory mTLS and disabled OAuth2 with an invalid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with an invalid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 401
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
+        Then the response status code should be 202
+
+    Scenario: Test mandatory mTLS and disabled OAuth2 without a client certificate in header
+        Given The system is ready
+        And I have a valid subscription
+        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 401
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
+        Then the response status code should be 202
+
+    Scenario: Test optional mTLS and enabled OAuth2 with a valid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test optional mTLS and enabled OAuth2 with an invalid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with an invalid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test optional mTLS and enabled OAuth2 without a client certificate in header
+        Given The system is ready
+        And I have a valid subscription
+        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization | bearer ${accessToken} |
+        And I wait for next minute
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test optional mTLS and disabled OAuth2 with a valid client certificate in header
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 406
+
+    Scenario: Test an API with mTLS disabled and OAuth2 disabled
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 406
+
+    Scenario: Test an API with mTLS disabled and OAuth2 enabled
+        Given The system is ready
+        And I have a valid subscription
+        When I use the APK Conf file "artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization | bearer ${accessToken} |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-disabled-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test an API with mTLS enabled and multiple certificates configured
+        Given The system is ready
+        And I have a valid subscription with a valid client certificate
+        When I use the APK Conf file "artifacts/apk-confs/mtls_multiple_certs.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
+        Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        Then the response status code should be 200
+        When I undeploy the API whose ID is "mtls-multiple-certs"
+        Then the response status code should be 202

From 99568af4e53bd38326cb2780f3e12b22d384ced1 Mon Sep 17 00:00:00 2001
From: sgayangi 
Date: Tue, 2 Jan 2024 18:50:34 +0530
Subject: [PATCH 13/15] Fix test case failures

---
 .../operator/controllers/dp/api_controller.go |  9 ++-
 .../operator/synchronizer/rest_api.go         |  5 +-
 adapter/internal/operator/utils/utils.go      |  7 +--
 .../ballerina/resources/apk-conf-schema.yaml  |  2 +-
 test/cucumber-tests/CRs/artifacts.yaml        | 56 ++++++++++++++++++-
 5 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go
index 09d9afd1c..3e723f475 100644
--- a/adapter/internal/operator/controllers/dp/api_controller.go
+++ b/adapter/internal/operator/controllers/dp/api_controller.go
@@ -913,11 +913,14 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context
 
 func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context,
 	authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) {
-	resolvedMutualSSL := dpv1alpha1.MutualSSL{}
+	var resolvedMutualSSL *dpv1alpha1.MutualSSL
 	for _, authentication := range authentications {
-		resolvedMutualSSL = utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication)
+		if resolvedMutualSSL == nil {
+			resolvedMutualSSL = &dpv1alpha1.MutualSSL{}
+		}
+		utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication, resolvedMutualSSL)
 	}
-	return &resolvedMutualSSL, nil
+	return resolvedMutualSSL, nil
 }
 
 func (apiReconciler *APIReconciler) getResolvedBackendsMapping(ctx context.Context,
diff --git a/adapter/internal/operator/synchronizer/rest_api.go b/adapter/internal/operator/synchronizer/rest_api.go
index 23b413bc7..d50f8bd40 100644
--- a/adapter/internal/operator/synchronizer/rest_api.go
+++ b/adapter/internal/operator/synchronizer/rest_api.go
@@ -58,9 +58,12 @@ func GenerateAdapterInternalAPI(apiState APIState, httpRoute *HTTPRouteState, en
 	adapterInternalAPI.SetAPIDefinitionFile(apiState.APIDefinitionFile)
 	adapterInternalAPI.SetAPIDefinitionEndpoint(apiState.APIDefinition.Spec.DefinitionPath)
 	adapterInternalAPI.SetSubscriptionValidation(apiState.SubscriptionValidation)
-	if apiState.MutualSSL != nil && !adapterInternalAPI.IsSystemAPI {
+	if apiState.MutualSSL != nil && apiState.MutualSSL.Required != "" && !adapterInternalAPI.IsSystemAPI {
+		adapterInternalAPI.SetDisableMtls(apiState.MutualSSL.Disabled)
 		adapterInternalAPI.SetMutualSSL(apiState.MutualSSL.Required)
 		adapterInternalAPI.SetClientCerts(apiState.APIDefinition.Name, apiState.MutualSSL.ClientCertificates)
+	} else {
+		adapterInternalAPI.SetDisableMtls(true)
 	}
 	adapterInternalAPI.EnvType = envType
 
diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go
index 376f22776..4043350ff 100644
--- a/adapter/internal/operator/utils/utils.go
+++ b/adapter/internal/operator/utils/utils.go
@@ -456,8 +456,7 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client,
 }
 
 // GetResolvedMutualSSL resolves mTLS related security configurations.
-func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication) dpv1alpha1.MutualSSL {
-	resolvedMutualSSL := dpv1alpha1.MutualSSL{}
+func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication, resolvedMutualSSL *dpv1alpha1.MutualSSL) {
 	var err error
 	var certificate string
 	var mutualSSL *dpv1alpha1.MutualSSLConfig
@@ -469,15 +468,13 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic
 	if mutualSSL != nil {
 		resolvedCertificates := ResolveAllmTLSCertificates(ctx, mutualSSL, certificate, err, client, authentication.Namespace)
 		resolvedMutualSSL.Disabled = mutualSSL.Disabled
-		resolvedMutualSSL.Required = authentication.Spec.Default.AuthTypes.MutualSSL.Required
+		resolvedMutualSSL.Required = mutualSSL.Required
 		resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, resolvedCertificates...)
 	}
 
 	if err != nil {
 		loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving mutual SSL %v in authentication", certificate))
 	}
-
-	return resolvedMutualSSL
 }
 
 // ResolveAllmTLSCertificates resolves all mTLS certificates
diff --git a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
index 552cebd5f..a9ea0ed48 100644
--- a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
+++ b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
@@ -155,7 +155,7 @@ components:
                 - optional
             certificates:
               type: array
-              description: The names and keys of the secrets containing the mTLS certificates of that API
+              description: The names and keys of the config maps containing the mTLS certificates of that API
               items:
                 type: object
                 properties:
diff --git a/test/cucumber-tests/CRs/artifacts.yaml b/test/cucumber-tests/CRs/artifacts.yaml
index 3f102e158..5289f9c02 100644
--- a/test/cucumber-tests/CRs/artifacts.yaml
+++ b/test/cucumber-tests/CRs/artifacts.yaml
@@ -730,4 +730,58 @@ metadata:
   namespace: apk-integration-test
 spec:
   applicationRef: 583e4146-7ef5-11ee-b962-0242ac120004
-  subscriptionRef: 583e4146-7ef6-11ee-b962-0242ac120003
\ No newline at end of file
+  subscriptionRef: 583e4146-7ef6-11ee-b962-0242ac120003
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: mtls-test-configmap
+  namespace: apk-integration-test
+data:
+  tls.crt: |
+    -----BEGIN CERTIFICATE-----
+    MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0x
+    CzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28y
+    MQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0y
+    NTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRl
+    MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3
+    DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9i
+    vVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/
+    a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwL
+    m7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2
+    qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQ
+    QxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZI
+    hvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp
+    1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6Uh
+    xZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McT
+    COKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBG
+    zUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinB
+    YlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=
+    -----END CERTIFICATE-----
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: mtls-test-configmap2
+  namespace: apk-integration-test
+data:
+  tls.crt: |
+    -----BEGIN CERTIFICATE-----
+    MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0x
+    CzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28y
+    MQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0y
+    NTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRl
+    MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3
+    DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9i
+    vVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/
+    a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwL
+    m7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2
+    qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQ
+    QxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZI
+    hvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp
+    1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6Uh
+    xZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McT
+    COKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBG
+    zUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinB
+    YlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=
+    -----END CERTIFICATE-----

From 094c3cf7358a9cdd62baeb2fdf1e3f079e80873d Mon Sep 17 00:00:00 2001
From: sgayangi 
Date: Fri, 5 Jan 2024 15:20:54 +0530
Subject: [PATCH 14/15] Add changes from code review

---
 .../operator/controllers/dp/api_controller.go |  10 +-
 .../operator/synchronizer/rest_api.go         |   2 +-
 adapter/internal/operator/utils/utils.go      |  20 +--
 .../apis/dp/v1alpha1/authentication_types.go  |   2 +
 .../dp/v1alpha1/authentication_webhook.go     |  31 +++--
 .../ballerina/APIClient.bal                   |   3 -
 .../ballerina/resources/apk-conf-schema.yaml  |   2 +-
 .../ballerina/tests/resources/apk-schema.json |   4 +-
 .../ballerina/types.bal                       |   2 +-
 .../config-deployer/conf/apk-schema.json      |   8 +-
 runtime/runtime-ui/schema/apk-conf.yaml       |   2 +
 runtime/runtime-ui/schema/apk-schema.json     |   4 +-
 test/cucumber-tests/CRs/artifacts.yaml        |  67 ++++++---
 .../integration/api/MTLSClientCertSteps.java  |  28 ++--
 .../mtls_disabled_oauth2_disabled.apk-conf    |   1 -
 .../mtls_disabled_oauth2_enabled.apk-conf     |   1 -
 .../mtls_mandatory_oauth2_disabled.apk-conf   |   0
 .../mtls_mandatory_oauth2_enabled.apk-conf    |   0
 .../{ => mtls}/mtls_multiple_certs.apk-conf   |   0
 .../mtls_optional_oauth2_disabled.apk-conf    |   1 -
 .../mtls_optional_oauth2_enabled.apk-conf     |   1 -
 .../artifacts/certificates/config-map-1.txt   |   1 +
 .../artifacts/certificates/config-map-2.txt   |   1 +
 .../artifacts/certificates/config-map-3.txt   |   1 +
 .../artifacts/certificates/invalid-cert.txt   |   1 +
 .../src/test/resources/tests/api/MTLS.feature | 130 ++++++++++++------
 26 files changed, 210 insertions(+), 113 deletions(-)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_disabled_oauth2_disabled.apk-conf (97%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_disabled_oauth2_enabled.apk-conf (96%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_mandatory_oauth2_disabled.apk-conf (100%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_mandatory_oauth2_enabled.apk-conf (100%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_multiple_certs.apk-conf (100%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_optional_oauth2_disabled.apk-conf (96%)
 rename test/cucumber-tests/src/test/resources/artifacts/apk-confs/{ => mtls}/mtls_optional_oauth2_enabled.apk-conf (96%)
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-1.txt
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-2.txt
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-3.txt
 create mode 100644 test/cucumber-tests/src/test/resources/artifacts/certificates/invalid-cert.txt

diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go
index 3e723f475..1186b77d6 100644
--- a/adapter/internal/operator/controllers/dp/api_controller.go
+++ b/adapter/internal/operator/controllers/dp/api_controller.go
@@ -913,14 +913,14 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context
 
 func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context,
 	authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) {
-	var resolvedMutualSSL *dpv1alpha1.MutualSSL
+	resolvedMutualSSL := dpv1alpha1.MutualSSL{}
 	for _, authentication := range authentications {
-		if resolvedMutualSSL == nil {
-			resolvedMutualSSL = &dpv1alpha1.MutualSSL{}
+		err := utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication, &resolvedMutualSSL)
+		if err != nil {
+			return nil, err
 		}
-		utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication, resolvedMutualSSL)
 	}
-	return resolvedMutualSSL, nil
+	return &resolvedMutualSSL, nil
 }
 
 func (apiReconciler *APIReconciler) getResolvedBackendsMapping(ctx context.Context,
diff --git a/adapter/internal/operator/synchronizer/rest_api.go b/adapter/internal/operator/synchronizer/rest_api.go
index d50f8bd40..bb968145c 100644
--- a/adapter/internal/operator/synchronizer/rest_api.go
+++ b/adapter/internal/operator/synchronizer/rest_api.go
@@ -58,7 +58,7 @@ func GenerateAdapterInternalAPI(apiState APIState, httpRoute *HTTPRouteState, en
 	adapterInternalAPI.SetAPIDefinitionFile(apiState.APIDefinitionFile)
 	adapterInternalAPI.SetAPIDefinitionEndpoint(apiState.APIDefinition.Spec.DefinitionPath)
 	adapterInternalAPI.SetSubscriptionValidation(apiState.SubscriptionValidation)
-	if apiState.MutualSSL != nil && apiState.MutualSSL.Required != "" && !adapterInternalAPI.IsSystemAPI {
+	if apiState.MutualSSL != nil && apiState.MutualSSL.Required != "" && !adapterInternalAPI.GetDisableAuthentications() {
 		adapterInternalAPI.SetDisableMtls(apiState.MutualSSL.Disabled)
 		adapterInternalAPI.SetMutualSSL(apiState.MutualSSL.Required)
 		adapterInternalAPI.SetClientCerts(apiState.APIDefinition.Name, apiState.MutualSSL.ClientCertificates)
diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go
index 4043350ff..31e328e45 100644
--- a/adapter/internal/operator/utils/utils.go
+++ b/adapter/internal/operator/utils/utils.go
@@ -456,9 +456,7 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client,
 }
 
 // GetResolvedMutualSSL resolves mTLS related security configurations.
-func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication, resolvedMutualSSL *dpv1alpha1.MutualSSL) {
-	var err error
-	var certificate string
+func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication, resolvedMutualSSL *dpv1alpha1.MutualSSL) error {
 	var mutualSSL *dpv1alpha1.MutualSSLConfig
 	if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil {
 		mutualSSL = authentication.Spec.Default.AuthTypes.MutualSSL
@@ -466,20 +464,24 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic
 		mutualSSL = authentication.Spec.Override.AuthTypes.MutualSSL
 	}
 	if mutualSSL != nil {
-		resolvedCertificates := ResolveAllmTLSCertificates(ctx, mutualSSL, certificate, err, client, authentication.Namespace)
+		resolvedCertificates, err := ResolveAllmTLSCertificates(ctx, mutualSSL, client, authentication.Namespace)
 		resolvedMutualSSL.Disabled = mutualSSL.Disabled
 		resolvedMutualSSL.Required = mutualSSL.Required
 		resolvedMutualSSL.ClientCertificates = append(resolvedMutualSSL.ClientCertificates, resolvedCertificates...)
-	}
 
-	if err != nil {
-		loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving mutual SSL %v in authentication", certificate))
+		if err != nil {
+			loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Error in resolving mutual SSL %v in authentication", mutualSSL))
+			return err
+		}
 	}
+	return nil
 }
 
 // ResolveAllmTLSCertificates resolves all mTLS certificates
-func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.MutualSSLConfig, certificate string, err error, client k8client.Client, namespace string) []string {
+func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.MutualSSLConfig, client k8client.Client, namespace string) ([]string, error) {
 	var resolvedCertificates []string
+	var err error
+	var certificate string
 	if mutualSSL.CertificatesInline != nil {
 		for _, cert := range mutualSSL.CertificatesInline {
 			certificate, err = ResolveCertificate(ctx, client, namespace, cert, nil, nil)
@@ -498,7 +500,7 @@ func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.Mutua
 			resolvedCertificates = append(resolvedCertificates, certificate)
 		}
 	}
-	return resolvedCertificates
+	return resolvedCertificates, err
 }
 
 // ResolveCertificate reads the certificate from TLSConfig, first checks the certificateInline field,
diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go
index 778f70626..6bdf75db5 100644
--- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go
+++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go
@@ -75,6 +75,8 @@ type MutualSSLConfig struct {
 
 	// Required indicates whether mutualSSL is mandatory or optional
 	// +kubebuilder:validation:Enum=mandatory;optional
+	// +kubebuilder:default=optional
+	// +optional
 	Required string `json:"required"`
 
 	// CertificatesInline is the Inline Certificate entry
diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
index 471102b00..fb3f69747 100644
--- a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
+++ b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
@@ -78,23 +78,38 @@ func (r *Authentication) ValidateAuthentication() error {
 		allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind,
 			"Invalid Kind is provided"))
 	}
+	var mutualSSL *MutualSSLConfig
 
-	if r.Spec.Default != nil && r.Spec.Default.Disabled != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil {
+	if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil {
 		isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled
-		isMTLSMandatory = strings.ToLower(r.Spec.Default.AuthTypes.MutualSSL.Required) == "mandatory"
-		isMTLSDisabled = r.Spec.Default.AuthTypes.MutualSSL.Disabled
+		mutualSSL = r.Spec.Default.AuthTypes.MutualSSL
+
+		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
+		isMTLSDisabled = mutualSSL.Disabled
 		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("authTypes"), r.Spec.Default.AuthTypes,
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes,
 				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
 		}
-	} else if r.Spec.Override != nil && r.Spec.Override.Disabled != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil {
+		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL,
+				"invalid mTLS configuration - certificates not provided"))
+		}
+
+	} else if r.Spec.Override != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil {
 		isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled
-		isMTLSMandatory = strings.ToLower(r.Spec.Override.AuthTypes.MutualSSL.Required) == "mandatory"
-		isMTLSDisabled = r.Spec.Override.AuthTypes.MutualSSL.Disabled
+		mutualSSL = r.Spec.Override.AuthTypes.MutualSSL
+
+		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
+		isMTLSDisabled = mutualSSL.Disabled
 		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("authTypes"), r.Spec.Override.AuthTypes,
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes,
 				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
 		}
+
+		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes.MutualSSL,
+				"invalid mTLS configuration - certificates not provided"))
+		}
 	}
 
 	if len(allErrs) > 0 {
diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal
index 3a0cd927e..fb0f08bc0 100644
--- a/runtime/config-deployer-service/ballerina/APIClient.bal
+++ b/runtime/config-deployer-service/ballerina/APIClient.bal
@@ -362,7 +362,6 @@ public class APIClient {
                     return e909019();
                 }
                 authTypes.mtls = {disabled: !mtlsAuthentication.enabled, configMapRefs: mtlsAuthentication.certificates, required: mtlsAuthentication.required};
-
             }
         }
         log:printDebug("Auth Types:" + authTypes.toString());
@@ -1400,8 +1399,6 @@ public class APIClient {
     private isolated function validateAndRetrieveAPKConfiguration(json apkconfJson) returns APKConf|commons:APKError? {
         do {
             runtimeapi:APKConfValidationResponse validationResponse = check apkConfValidator.validate(apkconfJson.toJsonString());
-            log:printInfo(apkconfJson.toJsonString());
-            log:printInfo(validationResponse.isValidated().toString());
 
             if validationResponse.isValidated() {
                 APKConf apkConf = check apkconfJson.cloneWithType(APKConf);
diff --git a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
index a9ea0ed48..63904355b 100644
--- a/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
+++ b/runtime/config-deployer-service/ballerina/resources/apk-conf-schema.yaml
@@ -149,7 +149,7 @@ components:
           properties:
             required:
               type: string
-              default: mandatory
+              default: optional
               enum:
                 - mandatory
                 - optional
diff --git a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
index 47846c036..f2a92cc9c 100644
--- a/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
+++ b/runtime/config-deployer-service/ballerina/tests/resources/apk-schema.json
@@ -150,13 +150,15 @@
         },
         "required": {
           "type": "string",
+          "default": "optional",
           "enum": [
             "mandatory",
             "optional"
           ]
         },
         "enabled": {
-          "type": "boolean"
+          "type": "boolean",
+          "default": true
         },
         "certificates": {
           "type": "array",
diff --git a/runtime/config-deployer-service/ballerina/types.bal b/runtime/config-deployer-service/ballerina/types.bal
index a32a549a6..7981a0843 100644
--- a/runtime/config-deployer-service/ballerina/types.bal
+++ b/runtime/config-deployer-service/ballerina/types.bal
@@ -275,7 +275,7 @@ public type APIKeyAuthentication record {|
 # + certificates - The list of config map refs referring to the client certificates
 public type MTLSAuthentication record {|
     *Authentication;
-    string required;
+    string required = "optional";
     ConfigMapRef[] certificates;
 |};
 
diff --git a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
index 47846c036..4c99894ba 100644
--- a/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
+++ b/runtime/config-deployer-service/docker/config-deployer/conf/apk-schema.json
@@ -150,13 +150,15 @@
         },
         "required": {
           "type": "string",
+          "default": "optional",
           "enum": [
             "mandatory",
             "optional"
           ]
         },
         "enabled": {
-          "type": "boolean"
+          "type": "boolean",
+          "default": true
         },
         "certificates": {
           "type": "array",
@@ -173,6 +175,10 @@
           }
         }
       },
+      "required": [
+        "authType",
+        "certificates"
+      ],
       "additionalProperties": false
     },
     "APIKeyAuthentication": {
diff --git a/runtime/runtime-ui/schema/apk-conf.yaml b/runtime/runtime-ui/schema/apk-conf.yaml
index 9400caacc..920fef175 100644
--- a/runtime/runtime-ui/schema/apk-conf.yaml
+++ b/runtime/runtime-ui/schema/apk-conf.yaml
@@ -117,9 +117,11 @@ schemas:
       enabled:
         type: boolean
         example: true
+        default: true
         description: Specifies whether mTLS authentication is enabled for the API.
       required:
         type: string
+        default: optional
         enum:
           - mandatory
           - optional
diff --git a/runtime/runtime-ui/schema/apk-schema.json b/runtime/runtime-ui/schema/apk-schema.json
index 47846c036..f2a92cc9c 100644
--- a/runtime/runtime-ui/schema/apk-schema.json
+++ b/runtime/runtime-ui/schema/apk-schema.json
@@ -150,13 +150,15 @@
         },
         "required": {
           "type": "string",
+          "default": "optional",
           "enum": [
             "mandatory",
             "optional"
           ]
         },
         "enabled": {
-          "type": "boolean"
+          "type": "boolean",
+          "default": true
         },
         "certificates": {
           "type": "array",
diff --git a/test/cucumber-tests/CRs/artifacts.yaml b/test/cucumber-tests/CRs/artifacts.yaml
index 5289f9c02..b1292f343 100644
--- a/test/cucumber-tests/CRs/artifacts.yaml
+++ b/test/cucumber-tests/CRs/artifacts.yaml
@@ -767,21 +767,54 @@ metadata:
 data:
   tls.crt: |
     -----BEGIN CERTIFICATE-----
-    MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0x
-    CzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28y
-    MQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0y
-    NTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRl
-    MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3
-    DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9i
-    vVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/
-    a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwL
-    m7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2
-    qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQ
-    QxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZI
-    hvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp
-    1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6Uh
-    xZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McT
-    COKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBG
-    zUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinB
-    YlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=
+    MIIDkTCCAnmgAwIBAgIUJitjysknJ0nHeLH/mjT1JIpOz4YwDQYJKoZIhvcNAQEL
+    BQAwYDELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTERMA8GA1UEBwwI
+    WW91ckNpdHkxGTAXBgNVBAoMEFlvdXJPcmdhbml6YXRpb24xDzANBgNVBAMMBllv
+    dXJDQTAeFw0yNDAxMDUwNDAwMjNaFw0yNTAxMDQwNDAwMjNaMGExCzAJBgNVBAYT
+    AlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MRkwFwYD
+    VQQKDBBZb3VyT3JnYW5pemF0aW9uMRAwDgYDVQQDDAdjbGllbnQxMIIBIjANBgkq
+    hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuJhFZmCVnj6N+/+HHuMvb4vyWqWcorUf
+    pAWO7a3YVsHp3BX+lbGGzh67jbPcFK6K7RqejenFw7sQK8duZlqXmik/JvZMLxY3
+    l/6e8LIAhN7PaX1zg58OU61baQ5VNBhUXkoYN77xqb87Yo7IFyyQ/tyWfRVFEzNj
+    V1+q2MpEinuscViieIQHEpB4i6fsRxomYkR+FwdfCB65MYCYveIB1z9NkmR6Pm6V
+    7zSPp+QYwc6WX4/61fbRje4BJh3j+FGYboJJg1o9O/MkD70RW6mdMV1l5bT9T98W
+    B+hJtN+5dEpSfAwXqlWWxzhDxNsEvdSwuoLz9e58gteR1LSLaJXMjQIDAQABo0Iw
+    QDAdBgNVHQ4EFgQULaoslUgyglywztd95CkL6sU5wa4wHwYDVR0jBBgwFoAUGUkK
+    +QXBjeGMy7XVnrXfrvVJUNswDQYJKoZIhvcNAQELBQADggEBABodQ1Y7zt7kvDI8
+    jQUfLLkZZAPnVpjYpG7P1dLjOzUxqDNmyZAzoBMENXy/Zu81sRQt+Bs5NKsx1pu5
+    z2TRk9ddxhszD1FKu9Hb6hqLcGHF7GnwPGVXJlHctkMp4QYvXc942VDk7c59/knC
+    PXAul7832cPTUMvFHdzRxBwJruK9xuvNLj2I24+Fji1ELPO7M/e8KZ1NrIS0Fdwn
+    DuDDw3kMkl0BlSrmvMBreSaIOU4mFhmepC97awZ/wZZ+4mpIdWIagZf01txue8o0
+    +8kdGkFsmoCpnJjNjpoQFAYLEdif00iLcRpwwW/saUuxqZC0aDnQCIeo0GSNet8t
+    HOXCkvQ=
+    -----END CERTIFICATE-----
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: mtls-test-configmap3
+  namespace: apk-integration-test
+data:
+  tls.crt: |
+    -----BEGIN CERTIFICATE-----
+    MIIDkTCCAnmgAwIBAgIUJitjysknJ0nHeLH/mjT1JIpOz4cwDQYJKoZIhvcNAQEL
+    BQAwYDELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTERMA8GA1UEBwwI
+    WW91ckNpdHkxGTAXBgNVBAoMEFlvdXJPcmdhbml6YXRpb24xDzANBgNVBAMMBllv
+    dXJDQTAeFw0yNDAxMDUwNDE0MTlaFw0yNTAxMDQwNDE0MTlaMGExCzAJBgNVBAYT
+    AlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MRkwFwYD
+    VQQKDBBZb3VyT3JnYW5pemF0aW9uMRAwDgYDVQQDDAdjbGllbnQyMIIBIjANBgkq
+    hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2JQ8LITwayvjrrHUmFT44lH3IF3fdPhr
+    pQgKx7Z295QD9Ocka2rOFu47tuIeNcLiBTSyRLOFDRwjW9WXfWk9ALtxbedJfDyy
+    us/kLxY+SdzHW7/5dFbupGOcs58A/sxMyGTJgiCBxsgsRFfhet7ekq/ypmj5B8L3
+    5FlGg5NS0mbZlTM6aapLnkqU907RcsmzpFQBfWOHlDdWJocKEHECBXcxiTQk72C7
+    s2tndES5ltX/Wc8U/kX/M9LDXhn1Ew+roeFf0HCpdg6BlnTknhYU9S1c4aYKB2Yx
+    LNx74CsKsnxPPcePTXPqZEtZ4EsjF4PSToVFyceMBKvD6C6WPQoRNwIDAQABo0Iw
+    QDAdBgNVHQ4EFgQUWE8btMihi5eZXLJOeiNfh7XHaI0wHwYDVR0jBBgwFoAUGUkK
+    +QXBjeGMy7XVnrXfrvVJUNswDQYJKoZIhvcNAQELBQADggEBAJmXn/gefez7mq1b
+    iKpPLPeHUncIgVaru03v8YCX14pHFAsVuLgZ1lANelSrq+PR/HBJbQj8iloV938o
+    YFppe/fb96D8a2u90dnGwWipMRSDo3wgcInL38xfcH5UEPBVJVLa3IUkfwDjjEqK
+    3O0GXVSpjyv3RW+E9wfPfGSysRX66cTo5Uh3z3hTAloDc8uhCYRPcxG7S9eKD6jW
+    Z3MlFlw4U8CdO90L0nB1KFhz1Et0Sl9u/LDsUYq6mE+XhTngPs8qwR/o43s1DUID
+    y5Oi4A4+id+xO0XnHIkkqCfPtFzxl3hwytcy8EqISynzzHWNJ8bFZIYX4tgX+PLq
+    u0/ITEw=
     -----END CERTIFICATE-----
diff --git a/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
index db0cf7fbf..735e56c62 100644
--- a/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
+++ b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/MTLSClientCertSteps.java
@@ -22,9 +22,13 @@
 import org.wso2.apk.integration.utils.Utils;
 import org.wso2.apk.integration.utils.clients.SimpleHTTPClient;
 
+import com.google.common.io.Resources;
+
 import io.cucumber.java.Before;
 import io.cucumber.java.en.Then;
 
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -47,8 +51,8 @@ public void setup() throws Exception {
                 httpClient = sharedContext.getHttpClient();
         }
 
-        @Then("I have a valid subscription with a valid client certificate")
-        public void getValidClientCertificateForMTLS() throws Exception {
+        @Then("I have a valid token with a client certificate {string}")
+        public void getValidClientCertificateForMTLS(String clientCertificatePath) throws Exception {
 
                 Map headers = new HashMap<>();
                 headers.put(Constants.REQUEST_HEADERS.HOST, Constants.DEFAULT_IDP_HOST);
@@ -60,24 +64,10 @@ public void getValidClientCertificateForMTLS() throws Exception {
                                 Constants.CONTENT_TYPES.APPLICATION_X_WWW_FORM_URLENCODED);
                 sharedContext.setAccessToken(Utils.extractToken(httpResponse));
                 sharedContext.addStoreValue("accessToken", sharedContext.getAccessToken());
-                sharedContext.addStoreValue("clientCertificate",
-                                "-----BEGIN CERTIFICATE-----MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28yMQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0yNTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9ivVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwLm7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQQxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6UhxZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McTCOKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBGzUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinBYlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=-----END CERTIFICATE-----");
-        }
-
-        @Then("I have a valid subscription with an invalid client certificate")
-        public void getInvalidClientCertificateForMTLS() throws Exception {
 
-                Map headers = new HashMap<>();
-                headers.put(Constants.REQUEST_HEADERS.HOST, Constants.DEFAULT_IDP_HOST);
-                headers.put(Constants.REQUEST_HEADERS.AUTHORIZATION,
-                                "Basic NDVmMWM1YzgtYTkyZS0xMWVkLWFmYTEtMDI0MmFjMTIwMDAyOjRmYmQ2MmVjLWE5MmUtMTFlZC1hZmExLTAyNDJhYzEyMDAwMg==");
+                URL url = Resources.getResource("artifacts/certificates/" + clientCertificatePath);
+                String clientCertificate = Resources.toString(url, StandardCharsets.UTF_8);
+                sharedContext.addStoreValue("clientCertificate", clientCertificate);
 
-                HttpResponse httpResponse = httpClient.doPost(Utils.getTokenEndpointURL(), headers,
-                                "grant_type=client_credentials&scope=" + Constants.API_CREATE_SCOPE,
-                                Constants.CONTENT_TYPES.APPLICATION_X_WWW_FORM_URLENCODED);
-                sharedContext.setAccessToken(Utils.extractToken(httpResponse));
-                sharedContext.addStoreValue("accessToken", sharedContext.getAccessToken());
-                sharedContext.addStoreValue("clientCertificate",
-                                "-----BEGIN CERTIFICATE-----MIIDJDCfeXw==-----END CERTIFICATE-----");
         }
 }
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_disabled.apk-conf
similarity index 97%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_disabled.apk-conf
index 28babf72f..2b434ccba 100644
--- a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_disabled.apk-conf
@@ -28,7 +28,6 @@ authentication:
   - authType: OAuth2
     enabled: false
   - authType: mTLS
-    required: optional
     enabled: false
     certificates:
       - name: mtls-test-configmap
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_enabled.apk-conf
similarity index 96%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_enabled.apk-conf
index 88602c950..7626fb2b5 100644
--- a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_disabled_oauth2_enabled.apk-conf
@@ -26,7 +26,6 @@ operations:
     scopes: []
 authentication:
   - authType: mTLS
-    required: optional
     enabled: false
     certificates:
       - name: mtls-test-configmap
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_mandatory_oauth2_disabled.apk-conf
similarity index 100%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_mandatory_oauth2_disabled.apk-conf
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf
similarity index 100%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_multiple_certs.apk-conf
similarity index 100%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_multiple_certs.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_multiple_certs.apk-conf
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_disabled.apk-conf
similarity index 96%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_disabled.apk-conf
index da984143c..c258d686b 100644
--- a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_disabled.apk-conf
@@ -28,7 +28,6 @@ authentication:
   - authType: OAuth2
     enabled: false
   - authType: mTLS
-    required: optional
     certificates:
       - name: mtls-test-configmap
         key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf
similarity index 96%
rename from test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf
rename to test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf
index e30922bdb..b2119e886 100644
--- a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf
+++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf
@@ -26,7 +26,6 @@ operations:
     scopes: []
 authentication:
   - authType: mTLS
-    required: optional
     certificates:
       - name: mtls-test-configmap
         key: tls.crt
diff --git a/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-1.txt b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-1.txt
new file mode 100644
index 000000000..5e94b0441
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-1.txt
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE-----MIIDGTCCAgECFANIkLQBkd76qiTXzSXjBS2scPJsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDAR3c28yMQwwCgYDVQQLDANhcGsxDDAKBgNVBAMMA2FwazAeFw0yMzEyMDYxMDEyNDhaFw0yNTA0MTkxMDEyNDhaMEUxCzAJBgNVBAYTAkxLMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdG90W/Tlk4u9awHPteD5zpVcThUKwMLvAKw9ivVQBC0AG6GzPbakol5gKVm+kBUDFzzzF6eayEXKWbyaZDty66A2+7HLLcKBop5M/a57Q9XtU3lRYvotgutLWuHcI7mLCScZDrjA3rnb/KjjbhZ602ZS1pp5jtyUz6DwLm7w4wQ/RProqCdBj8QqoAvnDDLSPeDfsx14J5VeNJVGJV2wax65jWRjRkj6wE7z2qzWAlP5vDeED6bogYYVDpC8DtgayQ+vKAQLi1uj+I9Yqb/nPUrdUh9IlxudlqiFQQxyvsXMJEzbWWmlbD0kXYkHmHzetJNPK9ayOS/fJcAcfAb01AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFmUc7+cI8d0Dl4wTdq+gfyWdqjQb7AYVO9DvJi3XGxdc5Kp1nCSsKzKUz9gvxXHeaYKrBNYf4SSU+Pkdf/BWePqi7UX/SIxNXby2da8zWg+W6UhxZfKlLYGMp3mCjueZpZTJ7SKOOGFA8IIgEzjJD9Ln1gl3ywMaCwlNrG9RpiD1McTCOKvyWNKnSRVr/RvCklLVrAMTJr50kce2czcdFl/xF4Hm66vp7cP/bYJKWAL8hBGzUa9aQBKncOoAO+zQ/SGy7uJxTDUF8SverDsmjOc6AU6IhBGVUyX/JQbYyJfZinBYlviYxVzIm6IaNJHx4sihw4U1/jMFWRXT470zcQ=-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-2.txt b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-2.txt
new file mode 100644
index 000000000..9e95fa5d5
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-2.txt
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE-----MIIDkTCCAnmgAwIBAgIUJitjysknJ0nHeLH/mjT1JIpOz4YwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTERMA8GA1UEBwwIWW91ckNpdHkxGTAXBgNVBAoMEFlvdXJPcmdhbml6YXRpb24xDzANBgNVBAMMBllvdXJDQTAeFw0yNDAxMDUwNDAwMjNaFw0yNTAxMDQwNDAwMjNaMGExCzAJBgNVBAYTAlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MRkwFwYDVQQKDBBZb3VyT3JnYW5pemF0aW9uMRAwDgYDVQQDDAdjbGllbnQxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuJhFZmCVnj6N+/+HHuMvb4vyWqWcorUfpAWO7a3YVsHp3BX+lbGGzh67jbPcFK6K7RqejenFw7sQK8duZlqXmik/JvZMLxY3l/6e8LIAhN7PaX1zg58OU61baQ5VNBhUXkoYN77xqb87Yo7IFyyQ/tyWfRVFEzNjV1+q2MpEinuscViieIQHEpB4i6fsRxomYkR+FwdfCB65MYCYveIB1z9NkmR6Pm6V7zSPp+QYwc6WX4/61fbRje4BJh3j+FGYboJJg1o9O/MkD70RW6mdMV1l5bT9T98WB+hJtN+5dEpSfAwXqlWWxzhDxNsEvdSwuoLz9e58gteR1LSLaJXMjQIDAQABo0IwQDAdBgNVHQ4EFgQULaoslUgyglywztd95CkL6sU5wa4wHwYDVR0jBBgwFoAUGUkK+QXBjeGMy7XVnrXfrvVJUNswDQYJKoZIhvcNAQELBQADggEBABodQ1Y7zt7kvDI8jQUfLLkZZAPnVpjYpG7P1dLjOzUxqDNmyZAzoBMENXy/Zu81sRQt+Bs5NKsx1pu5z2TRk9ddxhszD1FKu9Hb6hqLcGHF7GnwPGVXJlHctkMp4QYvXc942VDk7c59/knCPXAul7832cPTUMvFHdzRxBwJruK9xuvNLj2I24+Fji1ELPO7M/e8KZ1NrIS0FdwnDuDDw3kMkl0BlSrmvMBreSaIOU4mFhmepC97awZ/wZZ+4mpIdWIagZf01txue8o0+8kdGkFsmoCpnJjNjpoQFAYLEdif00iLcRpwwW/saUuxqZC0aDnQCIeo0GSNet8tHOXCkvQ=-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-3.txt b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-3.txt
new file mode 100644
index 000000000..a0088574c
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/certificates/config-map-3.txt
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE-----MIIDkTCCAnmgAwIBAgIUJitjysknJ0nHeLH/mjT1JIpOz4cwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTERMA8GA1UEBwwIWW91ckNpdHkxGTAXBgNVBAoMEFlvdXJPcmdhbml6YXRpb24xDzANBgNVBAMMBllvdXJDQTAeFw0yNDAxMDUwNDE0MTlaFw0yNTAxMDQwNDE0MTlaMGExCzAJBgNVBAYTAlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MRkwFwYDVQQKDBBZb3VyT3JnYW5pemF0aW9uMRAwDgYDVQQDDAdjbGllbnQyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2JQ8LITwayvjrrHUmFT44lH3IF3fdPhrpQgKx7Z295QD9Ocka2rOFu47tuIeNcLiBTSyRLOFDRwjW9WXfWk9ALtxbedJfDyyus/kLxY+SdzHW7/5dFbupGOcs58A/sxMyGTJgiCBxsgsRFfhet7ekq/ypmj5B8L35FlGg5NS0mbZlTM6aapLnkqU907RcsmzpFQBfWOHlDdWJocKEHECBXcxiTQk72C7s2tndES5ltX/Wc8U/kX/M9LDXhn1Ew+roeFf0HCpdg6BlnTknhYU9S1c4aYKB2YxLNx74CsKsnxPPcePTXPqZEtZ4EsjF4PSToVFyceMBKvD6C6WPQoRNwIDAQABo0IwQDAdBgNVHQ4EFgQUWE8btMihi5eZXLJOeiNfh7XHaI0wHwYDVR0jBBgwFoAUGUkK+QXBjeGMy7XVnrXfrvVJUNswDQYJKoZIhvcNAQELBQADggEBAJmXn/gefez7mq1biKpPLPeHUncIgVaru03v8YCX14pHFAsVuLgZ1lANelSrq+PR/HBJbQj8iloV938oYFppe/fb96D8a2u90dnGwWipMRSDo3wgcInL38xfcH5UEPBVJVLa3IUkfwDjjEqK3O0GXVSpjyv3RW+E9wfPfGSysRX66cTo5Uh3z3hTAloDc8uhCYRPcxG7S9eKD6jWZ3MlFlw4U8CdO90L0nB1KFhz1Et0Sl9u/LDsUYq6mE+XhTngPs8qwR/o43s1DUIDy5Oi4A4+id+xO0XnHIkkqCfPtFzxl3hwytcy8EqISynzzHWNJ8bFZIYX4tgX+PLqu0/ITEw=-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/artifacts/certificates/invalid-cert.txt b/test/cucumber-tests/src/test/resources/artifacts/certificates/invalid-cert.txt
new file mode 100644
index 000000000..6d1b1152d
--- /dev/null
+++ b/test/cucumber-tests/src/test/resources/artifacts/certificates/invalid-cert.txt
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE-----invalidcertificate-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature b/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature
index 5e802821a..aba613323 100644
--- a/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature
+++ b/test/cucumber-tests/src/test/resources/tests/api/MTLS.feature
@@ -1,153 +1,153 @@
 Feature: Test mTLS between client and gateway with client certificate sent in header
     Scenario: Test mandatory mTLS and enabled OAuth2 with a valid client certificate in header
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization             | bearer ${accessToken} |
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test mandatory mTLS and enabled OAuth2 with an invalid client certificate in header
         Given The system is ready
-        And I have a valid subscription with an invalid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        And I have a valid token with a client certificate "invalid-cert.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization             | bearer ${accessToken} |
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 401
+        And I eventually receive 401 response code, not accepting
+            | 200 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test mandatory mTLS and enabled OAuth2 without a client certificate in header
         Given The system is ready
         And I have a valid subscription
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_enabled.apk-conf"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization | bearer ${accessToken} |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 401
+        And I eventually receive 401 response code, not accepting
+            | 200 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test mandatory mTLS and disabled OAuth2 with a valid client certificate in header
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_disabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
         Then the response status code should be 202
 
     Scenario: Test mandatory mTLS and disabled OAuth2 with an invalid client certificate in header
         Given The system is ready
-        And I have a valid subscription with an invalid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        And I have a valid token with a client certificate "invalid-cert.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_disabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 401
+        And I eventually receive 401 response code, not accepting
+            | 200 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
         Then the response status code should be 202
 
     Scenario: Test mandatory mTLS and disabled OAuth2 without a client certificate in header
         Given The system is ready
         And I have a valid subscription
-        When I use the APK Conf file "artifacts/apk-confs/mtls_mandatory_oauth2_disabled.apk-conf"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_disabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 401
+        And I eventually receive 401 response code, not accepting
+            | 200 |
         When I undeploy the API whose ID is "mtls-mandatory-oauth2-disabled"
         Then the response status code should be 202
 
     Scenario: Test optional mTLS and enabled OAuth2 with a valid client certificate in header
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization             | bearer ${accessToken} |
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test optional mTLS and enabled OAuth2 with an invalid client certificate in header
         Given The system is ready
-        And I have a valid subscription with an invalid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        And I have a valid token with a client certificate "invalid-cert.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization             | bearer ${accessToken} |
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test optional mTLS and enabled OAuth2 without a client certificate in header
         Given The system is ready
         And I have a valid subscription
-        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_enabled.apk-conf"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_optional_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization | bearer ${accessToken} |
-        And I wait for next minute
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-optional-oauth2-enabled"
         Then the response status code should be 202
 
     Scenario: Test optional mTLS and disabled OAuth2 with a valid client certificate in header
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_optional_oauth2_disabled.apk-conf"
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_optional_oauth2_disabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 406
 
     Scenario: Test an API with mTLS disabled and OAuth2 disabled
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_disabled_oauth2_disabled.apk-conf"
+        And I have a valid subscription
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_disabled_oauth2_disabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 406
@@ -155,21 +155,22 @@ Feature: Test mTLS between client and gateway with client certificate sent in he
     Scenario: Test an API with mTLS disabled and OAuth2 enabled
         Given The system is ready
         And I have a valid subscription
-        When I use the APK Conf file "artifacts/apk-confs/mtls_disabled_oauth2_enabled.apk-conf"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_disabled_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
         Then I set headers
             | Authorization | bearer ${accessToken} |
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
-        Then the response status code should be 200
+        And I eventually receive 200 response code, not accepting
+            | 401 |
         When I undeploy the API whose ID is "mtls-disabled-oauth2-enabled"
         Then the response status code should be 202
 
-    Scenario: Test an API with mTLS enabled and multiple certificates configured
+    Scenario: Test an API with mTLS enabled and one associated certificate with multiple certificates existing in system
         Given The system is ready
-        And I have a valid subscription with a valid client certificate
-        When I use the APK Conf file "artifacts/apk-confs/mtls_multiple_certs.apk-conf"
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_mandatory_oauth2_enabled.apk-conf"
         And the definition file "artifacts/definitions/employees_api.json"
         And make the API deployment request
         Then the response status code should be 200
@@ -177,6 +178,51 @@ Feature: Test mTLS between client and gateway with client certificate sent in he
             | Authorization             | bearer ${accessToken} |
             | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
         And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 200 response code, not accepting
+            | 401 |
+        And I have a valid token with a client certificate "config-map-2.txt"
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 401 response code, not accepting
+            | 200 |
+        And I have a valid token with a client certificate "config-map-3.txt"
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 401 response code, not accepting
+            | 200 |
+        When I undeploy the API whose ID is "mtls-mandatory-oauth2-enabled"
+        Then the response status code should be 202
+
+    Scenario: Test an API with mTLS enabled and multiple certificates configured
+        Given The system is ready
+        And I have a valid token with a client certificate "config-map-1.txt"
+        When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_multiple_certs.apk-conf"
+        And the definition file "artifacts/definitions/employees_api.json"
+        And make the API deployment request
         Then the response status code should be 200
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 200 response code, not accepting
+            | 401 |
+        And I have a valid token with a client certificate "config-map-2.txt"
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 200 response code, not accepting
+            | 401 |
+        And I have a valid token with a client certificate "config-map-3.txt"
+        Then I set headers
+            | Authorization             | bearer ${accessToken} |
+            | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate}  |
+        And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body ""
+        And I eventually receive 401 response code, not accepting
+            | 200 |
         When I undeploy the API whose ID is "mtls-multiple-certs"
         Then the response status code should be 202

From 98ca8f63dbfa5a28dba70ece7b41366aab9b2d6c Mon Sep 17 00:00:00 2001
From: sgayangi 
Date: Tue, 9 Jan 2024 21:46:10 +0530
Subject: [PATCH 15/15] Add changes from code review

---
 .../oasparser/model/adapter_internal_api.go   |  24 +-
 .../internal/oasparser/model/http_route.go    |  12 +-
 adapter/internal/operator/PROJECT             |   9 +
 .../bases/dp.wso2.com_authentications.yaml    | 217 ++++++-
 .../operator/config/webhook/manifests.yaml    |  90 ++-
 .../operator/controllers/dp/api_controller.go |  57 +-
 .../operator/synchronizer/api_state.go        |   6 +-
 .../synchronizer/zz_generated.deepcopy.go     |   6 +-
 adapter/internal/operator/utils/utils.go      |  18 +-
 .../bases/dp.wso2.com_authentications.yaml    | 558 ++++++++++++++++++
 .../operator/config/crd/kustomization.yaml    |   1 +
 .../cainjection_in_dp_authentications.yaml    |   7 +
 .../webhook_in_dp_authentications.yaml        |  16 +
 .../rbac/dp_authentication_editor_role.yaml   |  31 +
 .../rbac/dp_authentication_viewer_role.yaml   |  27 +
 .../samples/dp_v1alpha2_authentication.yaml   |  12 +
 .../operator/config/webhook/manifests.yaml    |  40 ++
 .../internal/operator/operator.go             |   2 +-
 common-go-libs/PROJECT                        |  14 +
 .../dp/v1alpha1/authentication_conversion.go  |  86 +++
 .../apis/dp/v1alpha1/authentication_types.go  |  30 -
 .../dp/v1alpha1/authentication_webhook.go     |  38 --
 .../apis/dp/v1alpha1/zz_generated.deepcopy.go |  73 ---
 .../dp/v1alpha2/authentication_conversion.go  |  21 +
 .../apis/dp/v1alpha2/authentication_types.go  | 178 ++++++
 .../dp/v1alpha2/authentication_webhook.go     | 126 ++++
 .../dp/{v1alpha1 => v1alpha2}/mutualSSL.go    |   4 +-
 .../apis/dp/v1alpha2/webhook_suite_test.go    |   3 +
 .../apis/dp/v1alpha2/zz_generated.deepcopy.go | 265 +++++++++
 .../bases/dp.wso2.com_authentications.yaml    | 214 ++++++-
 common-go-libs/config/webhook/manifests.yaml  |  40 ++
 .../org/wso2/apk/enforcer/api/GraphQLAPI.java |   9 +-
 .../crds/dp.wso2.com_authentications.yaml     | 217 ++++++-
 .../adapter-mutating-webhook-config.yaml      |   6 +-
 .../adapter-validation-webhook-config.yaml    |   4 +-
 .../ballerina/K8sClient.bal                   |  15 +-
 .../modules/model/Authentication.bal          |   4 +-
 37 files changed, 2225 insertions(+), 255 deletions(-)
 create mode 100644 common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
 create mode 100644 common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml
 create mode 100644 common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml
 create mode 100644 common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml
 create mode 100644 common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml
 create mode 100644 common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml
 create mode 100644 common-go-libs/apis/dp/v1alpha1/authentication_conversion.go
 create mode 100644 common-go-libs/apis/dp/v1alpha2/authentication_conversion.go
 create mode 100644 common-go-libs/apis/dp/v1alpha2/authentication_types.go
 create mode 100644 common-go-libs/apis/dp/v1alpha2/authentication_webhook.go
 rename common-go-libs/apis/dp/{v1alpha1 => v1alpha2}/mutualSSL.go (90%)

diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go
index 32a9068b3..80f7eb75d 100644
--- a/adapter/internal/oasparser/model/adapter_internal_api.go
+++ b/adapter/internal/oasparser/model/adapter_internal_api.go
@@ -313,8 +313,8 @@ func (adapterInternalAPI *AdapterInternalAPI) GetDisableScopes() bool {
 }
 
 // GetDisableMtls returns whether mTLS is disabled or not
-func (swagger *AdapterInternalAPI) GetDisableMtls() bool {
-	return swagger.disableMtls
+func (adapterInternalAPI *AdapterInternalAPI) GetDisableMtls() bool {
+	return adapterInternalAPI.disableMtls
 }
 
 // GetID returns the Id of the API
@@ -340,7 +340,7 @@ func (adapterInternalAPI *AdapterInternalAPI) GetClientCerts() []Certificate {
 }
 
 // SetClientCerts set the client certificates of the API
-func (swagger *AdapterInternalAPI) SetClientCerts(apiName string, certs []string) {
+func (adapterInternalAPI *AdapterInternalAPI) SetClientCerts(apiName string, certs []string) {
 	var clientCerts []Certificate
 	for i, cert := range certs {
 		clientCert := Certificate{
@@ -349,7 +349,7 @@ func (swagger *AdapterInternalAPI) SetClientCerts(apiName string, certs []string
 		}
 		clientCerts = append(clientCerts, clientCert)
 	}
-	swagger.clientCertificates = clientCerts
+	adapterInternalAPI.clientCertificates = clientCerts
 }
 
 // SetID set the Id of the API
@@ -400,18 +400,18 @@ func (adapterInternalAPI *AdapterInternalAPI) GetXWSO2AuthHeader() string {
 }
 
 // SetMutualSSL sets the optional or mandatory mTLS
-func (swagger *AdapterInternalAPI) SetMutualSSL(mutualSSL string) {
-	swagger.mutualSSL = mutualSSL
+func (adapterInternalAPI *AdapterInternalAPI) SetMutualSSL(mutualSSL string) {
+	adapterInternalAPI.mutualSSL = mutualSSL
 }
 
 // GetMutualSSL returns the optional or mandatory mTLS
-func (swagger *AdapterInternalAPI) GetMutualSSL() string {
-	return swagger.mutualSSL
+func (adapterInternalAPI *AdapterInternalAPI) GetMutualSSL() string {
+	return adapterInternalAPI.mutualSSL
 }
 
 // SetDisableMtls returns whether mTLS is disabled or not
-func (swagger *AdapterInternalAPI) SetDisableMtls(disableMtls bool) {
-	swagger.disableMtls = disableMtls
+func (adapterInternalAPI *AdapterInternalAPI) SetDisableMtls(disableMtls bool) {
+	adapterInternalAPI.disableMtls = disableMtls
 }
 
 // SetXWSO2ApplicationSecurity sets the optional or mandatory application security
@@ -469,7 +469,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoHTTPRouteCR(httpRoute *gwap
 	disableScopes := true
 	config := config.ReadConfigs()
 
-	var authScheme *dpv1alpha1.Authentication
+	var authScheme *dpv1alpha2.Authentication
 	if outputAuthScheme != nil {
 		authScheme = *outputAuthScheme
 	}
@@ -800,7 +800,7 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoGQLRouteCR(gqlRoute *dpv1al
 	disableScopes := true
 	config := config.ReadConfigs()
 
-	var authScheme *dpv1alpha1.Authentication
+	var authScheme *dpv1alpha2.Authentication
 	if outputAuthScheme != nil {
 		authScheme = *outputAuthScheme
 	}
diff --git a/adapter/internal/oasparser/model/http_route.go b/adapter/internal/oasparser/model/http_route.go
index 0977293e9..c62ededd5 100644
--- a/adapter/internal/oasparser/model/http_route.go
+++ b/adapter/internal/oasparser/model/http_route.go
@@ -30,8 +30,8 @@ import (
 
 // ResourceParams contains httproute related parameters
 type ResourceParams struct {
-	AuthSchemes               map[string]dpv1alpha1.Authentication
-	ResourceAuthSchemes       map[string]dpv1alpha1.Authentication
+	AuthSchemes               map[string]dpv1alpha2.Authentication
+	ResourceAuthSchemes       map[string]dpv1alpha2.Authentication
 	APIPolicies               map[string]dpv1alpha2.APIPolicy
 	ResourceAPIPolicies       map[string]dpv1alpha2.APIPolicy
 	InterceptorServiceMapping map[string]dpv1alpha1.InterceptorService
@@ -207,9 +207,9 @@ func concatAPIPolicies(schemeUp *dpv1alpha2.APIPolicy, schemeDown *dpv1alpha2.AP
 	return &apiPolicy
 }
 
-func concatAuthSchemes(schemeUp *dpv1alpha1.Authentication, schemeDown *dpv1alpha1.Authentication) *dpv1alpha1.Authentication {
-	finalAuth := dpv1alpha1.Authentication{
-		Spec: dpv1alpha1.AuthenticationSpec{},
+func concatAuthSchemes(schemeUp *dpv1alpha2.Authentication, schemeDown *dpv1alpha2.Authentication) *dpv1alpha2.Authentication {
+	finalAuth := dpv1alpha2.Authentication{
+		Spec: dpv1alpha2.AuthenticationSpec{},
 	}
 	if schemeUp != nil && schemeDown != nil {
 		finalAuth.Spec.Override = utils.SelectPolicy(&schemeUp.Spec.Override, &schemeUp.Spec.Default, &schemeDown.Spec.Override, &schemeDown.Spec.Default)
@@ -224,7 +224,7 @@ func concatAuthSchemes(schemeUp *dpv1alpha1.Authentication, schemeDown *dpv1alph
 // getSecurity returns security schemes and it's definitions with flag to indicate if security is disabled
 // make sure authscheme only has external service override values. (i.e. empty default values)
 // tip: use concatScheme method
-func getSecurity(authScheme *dpv1alpha1.Authentication) *Authentication {
+func getSecurity(authScheme *dpv1alpha2.Authentication) *Authentication {
 	authHeader := constants.AuthorizationHeader
 	if authScheme != nil && authScheme.Spec.Override != nil && authScheme.Spec.Override.AuthTypes != nil && len(authScheme.Spec.Override.AuthTypes.Oauth2.Header) > 0 {
 		authHeader = authScheme.Spec.Override.AuthTypes.Oauth2.Header
diff --git a/adapter/internal/operator/PROJECT b/adapter/internal/operator/PROJECT
index a20a3f8f3..1c9a275a4 100644
--- a/adapter/internal/operator/PROJECT
+++ b/adapter/internal/operator/PROJECT
@@ -129,6 +129,15 @@ resources:
   kind: API
   path: github.com/wso2/apk/adapter/internal/operator/apis/dp/v1alpha2
   version: v1alpha2
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: wso2.com
+  group: dp
+  kind: Authentication
+  path: github.com/wso2/apk/adapter/internal/operator/apis/dp/v1alpha2
+  version: v1alpha2
 - api:
     crdVersion: v1
     namespaced: true
diff --git a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
index 1dbc523a5..f1e5242cf 100644
--- a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
+++ b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.2
-  creationTimestamp: null
+    controller-gen.kubebuilder.io/version: v0.12.0
   name: authentications.dp.wso2.com
 spec:
   group: dp.wso2.com
@@ -16,6 +15,214 @@ spec:
   scope: Namespaced
   versions:
   - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Authentication is the Schema for the authentications API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: AuthenticationSpec defines the desired state of Authentication
+            properties:
+              default:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              override:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              targetRef:
+                description: PolicyTargetReference identifies an API object to apply
+                  policy to. This should be used as part of Policy resources that
+                  can target Gateway API resources. For more information on how this
+                  policy attachment model works, and a sample Policy resource, refer
+                  to the policy attachment documentation for Gateway API.
+                properties:
+                  group:
+                    description: Group is the group of the target resource.
+                    maxLength: 253
+                    pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                    type: string
+                  kind:
+                    description: Kind is kind of the target resource.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                    type: string
+                  name:
+                    description: Name is the name of the target resource.
+                    maxLength: 253
+                    minLength: 1
+                    type: string
+                  namespace:
+                    description: Namespace is the namespace of the referent. When
+                      unspecified, the local namespace is inferred. Even when policy
+                      targets a resource in a different namespace, it MUST only apply
+                      to traffic originating from the same namespace as the policy.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                    type: string
+                required:
+                - group
+                - kind
+                - name
+                type: object
+            type: object
+          status:
+            description: AuthenticationStatus defines the observed state of Authentication
+            type: object
+        type: object
+    served: true
+    storage: false
+    subresources:
+      status: {}
+  - name: v1alpha2
     schema:
       openAPIV3Schema:
         description: Authentication is the Schema for the authentications API
@@ -103,6 +310,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -129,8 +337,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
@@ -238,6 +444,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -264,8 +471,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
diff --git a/adapter/internal/operator/config/webhook/manifests.yaml b/adapter/internal/operator/config/webhook/manifests.yaml
index 474f6dc2f..411ed6ee8 100644
--- a/adapter/internal/operator/config/webhook/manifests.yaml
+++ b/adapter/internal/operator/config/webhook/manifests.yaml
@@ -2,7 +2,6 @@
 apiVersion: admissionregistration.k8s.io/v1
 kind: MutatingWebhookConfiguration
 metadata:
-  creationTimestamp: null
   name: mutating-webhook-configuration
 webhooks:
 - admissionReviewVersions:
@@ -11,14 +10,14 @@ webhooks:
     service:
       name: webhook-service
       namespace: system
-      path: /mutate-dp-wso2-com-v1alpha1-api
+      path: /mutate-dp-wso2-com-v1alpha2-api
   failurePolicy: Fail
   name: mapi.kb.io
   rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
-    - v1alpha1
+    - v1alpha2
     operations:
     - CREATE
     - UPDATE
@@ -35,6 +34,46 @@ webhooks:
   failurePolicy: Fail
   name: mapipolicy.kb.io
   rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - apipolicies
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: mauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-dp-wso2-com-v1alpha1-apipolicy
+  failurePolicy: Fail
+  name: mapipolicy.kb.io
+  rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
@@ -149,7 +188,6 @@ webhooks:
 apiVersion: admissionregistration.k8s.io/v1
 kind: ValidatingWebhookConfiguration
 metadata:
-  creationTimestamp: null
   name: validating-webhook-configuration
 webhooks:
 - admissionReviewVersions:
@@ -158,14 +196,14 @@ webhooks:
     service:
       name: webhook-service
       namespace: system
-      path: /validate-dp-wso2-com-v1alpha1-api
+      path: /validate-dp-wso2-com-v1alpha2-api
   failurePolicy: Fail
   name: vapi.kb.io
   rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
-    - v1alpha1
+    - v1alpha2
     operations:
     - CREATE
     - UPDATE
@@ -182,6 +220,46 @@ webhooks:
   failurePolicy: Fail
   name: vapipolicy.kb.io
   rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - apipolicies
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: vauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-dp-wso2-com-v1alpha1-apipolicy
+  failurePolicy: Fail
+  name: vapipolicy.kb.io
+  rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go
index 1186b77d6..f1403f1d8 100644
--- a/adapter/internal/operator/controllers/dp/api_controller.go
+++ b/adapter/internal/operator/controllers/dp/api_controller.go
@@ -152,7 +152,7 @@ func NewAPIController(mgr manager.Manager, operatorDataStore *synchronizer.Opera
 		return err
 	}
 
-	if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha1.Authentication{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.getAPIsForAuthentication),
+	if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha2.Authentication{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.getAPIsForAuthentication),
 		predicates...); err != nil {
 		loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2616, logging.BLOCKER, "Error watching Authentication resources: %v", err))
 		return err
@@ -671,10 +671,10 @@ func (apiReconciler *APIReconciler) concatHTTPRoutes(ctx context.Context, httpRo
 }
 
 func (apiReconciler *APIReconciler) getAuthenticationsForAPI(ctx context.Context,
-	api dpv1alpha2.API) (map[string]dpv1alpha1.Authentication, error) {
+	api dpv1alpha2.API) (map[string]dpv1alpha2.Authentication, error) {
 	nameSpacedName := utils.NamespacedName(&api).String()
-	authentications := make(map[string]dpv1alpha1.Authentication)
-	authenticationList := &dpv1alpha1.AuthenticationList{}
+	authentications := make(map[string]dpv1alpha2.Authentication)
+	authenticationList := &dpv1alpha2.AuthenticationList{}
 	if err := apiReconciler.client.List(ctx, authenticationList, &k8client.ListOptions{
 		FieldSelector: fields.OneTermEqualSelector(apiAuthenticationIndex, nameSpacedName),
 	}); err != nil {
@@ -753,10 +753,10 @@ func (apiReconciler *APIReconciler) getScopesForHTTPRoute(ctx context.Context,
 }
 
 func (apiReconciler *APIReconciler) getAuthenticationsForResources(ctx context.Context,
-	api dpv1alpha2.API) (map[string]dpv1alpha1.Authentication, error) {
+	api dpv1alpha2.API) (map[string]dpv1alpha2.Authentication, error) {
 	nameSpacedName := utils.NamespacedName(&api).String()
-	authentications := make(map[string]dpv1alpha1.Authentication)
-	authenticationList := &dpv1alpha1.AuthenticationList{}
+	authentications := make(map[string]dpv1alpha2.Authentication)
+	authenticationList := &dpv1alpha2.AuthenticationList{}
 	if err := apiReconciler.client.List(ctx, authenticationList, &k8client.ListOptions{
 		FieldSelector: fields.OneTermEqualSelector(apiAuthenticationResourceIndex, nameSpacedName),
 	}); err != nil {
@@ -912,8 +912,8 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context
 }
 
 func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context,
-	authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) {
-	resolvedMutualSSL := dpv1alpha1.MutualSSL{}
+	authentications map[string]dpv1alpha2.Authentication) (*dpv1alpha2.MutualSSL, error) {
+	resolvedMutualSSL := dpv1alpha2.MutualSSL{}
 	for _, authentication := range authentications {
 		err := utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication, &resolvedMutualSSL)
 		if err != nil {
@@ -1101,7 +1101,7 @@ func (apiReconciler *APIReconciler) getAPIsForSecret(ctx context.Context, obj k8
 // from Authentication objects. If the changes are done for an API stored in the Operator Data store,
 // a new reconcile event will be created and added to the reconcile event queue.
 func (apiReconciler *APIReconciler) getAPIsForAuthentication(ctx context.Context, obj k8client.Object) []reconcile.Request {
-	authentication, ok := obj.(*dpv1alpha1.Authentication)
+	authentication, ok := obj.(*dpv1alpha2.Authentication)
 	if !ok {
 		loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", authentication))
 		return []reconcile.Request{}
@@ -1109,13 +1109,6 @@ func (apiReconciler *APIReconciler) getAPIsForAuthentication(ctx context.Context
 
 	requests := []reconcile.Request{}
 
-	// todo(amali) move this validation to validation hook
-	if !(authentication.Spec.TargetRef.Kind == constants.KindAPI || authentication.Spec.TargetRef.Kind == constants.KindResource) {
-		loggers.LoggerAPKOperator.Errorf("Unsupported target ref kind : %s was given for authentication: %s",
-			authentication.Spec.TargetRef.Kind, authentication.Name)
-		return requests
-	}
-
 	namespace, err := utils.ValidateAndRetrieveNamespace((*gwapiv1b1.Namespace)(authentication.Spec.TargetRef.Namespace), authentication.Namespace)
 
 	if err != nil {
@@ -1553,9 +1546,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error {
 	}
 
 	// authentication to API indexer
-	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, apiAuthenticationIndex,
+	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, apiAuthenticationIndex,
 		func(rawObj k8client.Object) []string {
-			authentication := rawObj.(*dpv1alpha1.Authentication)
+			authentication := rawObj.(*dpv1alpha2.Authentication)
 			var apis []string
 			if authentication.Spec.TargetRef.Kind == constants.KindAPI {
 
@@ -1579,9 +1572,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error {
 	}
 
 	// Secret to Authentication indexer
-	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, secretAuthentication,
+	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, secretAuthentication,
 		func(rawObj k8client.Object) []string {
-			authentication := rawObj.(*dpv1alpha1.Authentication)
+			authentication := rawObj.(*dpv1alpha2.Authentication)
 			var secrets []string
 			if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs) > 0 {
 				for _, secret := range authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs {
@@ -1613,9 +1606,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error {
 	}
 
 	// ConfigMap to Authentication indexer
-	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, configMapAuthentication,
+	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, configMapAuthentication,
 		func(rawObj k8client.Object) []string {
-			authentication := rawObj.(*dpv1alpha1.Authentication)
+			authentication := rawObj.(*dpv1alpha2.Authentication)
 			var configMaps []string
 			if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs) > 0 {
 				for _, configMap := range authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs {
@@ -1650,9 +1643,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error {
 	// https://gateway-api.sigs.k8s.io/geps/gep-713/?h=multiple+targetrefs#apply-policies-to-sections-of-a-resource-future-extension
 	// we will use a temporary kindName called Resource for policy attachments
 	// TODO(amali) Fix after the official support is available
-	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, apiAuthenticationResourceIndex,
+	if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, apiAuthenticationResourceIndex,
 		func(rawObj k8client.Object) []string {
-			authentication := rawObj.(*dpv1alpha1.Authentication)
+			authentication := rawObj.(*dpv1alpha2.Authentication)
 			var apis []string
 			if authentication.Spec.TargetRef.Kind == constants.KindResource {
 
@@ -1802,20 +1795,6 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error {
 						Name:      string(apiPolicy.Spec.Override.BackendJWTPolicy.Name),
 					}.String())
 			}
-			// if apiPolicy.Spec.Default != nil && apiPolicy.Spec.Default.BackendJWTPolicy != nil {
-			// 	backendJWTs = append(backendJWTs,
-			// 		types.NamespacedName{
-			// 			Namespace: apiPolicy.Namespace,
-			// 			Name:      string(apiPolicy.Spec.Default.BackendJWTPolicy.Name),
-			// 		}.String())
-			// }
-			// if apiPolicy.Spec.Override != nil && apiPolicy.Spec.Override.BackendJWTPolicy != nil {
-			// 	backendJWTs = append(backendJWTs,
-			// 		types.NamespacedName{
-			// 			Namespace: apiPolicy.Namespace,
-			// 			Name:      string(apiPolicy.Spec.Override.BackendJWTPolicy.Name),
-			// 		}.String())
-			// }
 			return backendJWTs
 		}); err != nil {
 		return err
diff --git a/adapter/internal/operator/synchronizer/api_state.go b/adapter/internal/operator/synchronizer/api_state.go
index 5490cc505..e15717249 100644
--- a/adapter/internal/operator/synchronizer/api_state.go
+++ b/adapter/internal/operator/synchronizer/api_state.go
@@ -32,9 +32,9 @@ type APIState struct {
 	SandHTTPRoute             *HTTPRouteState
 	ProdGQLRoute              *GQLRouteState
 	SandGQLRoute              *GQLRouteState
-	Authentications           map[string]v1alpha1.Authentication
+	Authentications           map[string]v1alpha2.Authentication
 	RateLimitPolicies         map[string]v1alpha1.RateLimitPolicy
-	ResourceAuthentications   map[string]v1alpha1.Authentication
+	ResourceAuthentications   map[string]v1alpha2.Authentication
 	ResourceRateLimitPolicies map[string]v1alpha1.RateLimitPolicy
 	ResourceAPIPolicies       map[string]v1alpha2.APIPolicy
 	APIPolicies               map[string]v1alpha2.APIPolicy
@@ -43,7 +43,7 @@ type APIState struct {
 	APIDefinitionFile         []byte
 	OldOrganizationID         string
 	SubscriptionValidation    bool
-	MutualSSL                 *v1alpha1.MutualSSL
+	MutualSSL                 *v1alpha2.MutualSSL
 }
 
 // HTTPRouteState holds the state of the deployed httpRoutes. This state is compared with
diff --git a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go
index b89dffe25..f2dc5002c 100644
--- a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go
+++ b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go
@@ -58,7 +58,7 @@ func (in *APIState) DeepCopyInto(out *APIState) {
 	}
 	if in.Authentications != nil {
 		in, out := &in.Authentications, &out.Authentications
-		*out = make(map[string]v1alpha1.Authentication, len(*in))
+		*out = make(map[string]v1alpha2.Authentication, len(*in))
 		for key, val := range *in {
 			(*out)[key] = *val.DeepCopy()
 		}
@@ -72,7 +72,7 @@ func (in *APIState) DeepCopyInto(out *APIState) {
 	}
 	if in.ResourceAuthentications != nil {
 		in, out := &in.ResourceAuthentications, &out.ResourceAuthentications
-		*out = make(map[string]v1alpha1.Authentication, len(*in))
+		*out = make(map[string]v1alpha2.Authentication, len(*in))
 		for key, val := range *in {
 			(*out)[key] = *val.DeepCopy()
 		}
@@ -119,7 +119,7 @@ func (in *APIState) DeepCopyInto(out *APIState) {
 	}
 	if in.MutualSSL != nil {
 		in, out := &in.MutualSSL, &out.MutualSSL
-		*out = new(v1alpha1.MutualSSL)
+		*out = new(v1alpha2.MutualSSL)
 		(*in).DeepCopyInto(*out)
 	}
 }
diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go
index 31e328e45..f9e66c596 100644
--- a/adapter/internal/operator/utils/utils.go
+++ b/adapter/internal/operator/utils/utils.go
@@ -456,13 +456,13 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client,
 }
 
 // GetResolvedMutualSSL resolves mTLS related security configurations.
-func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication, resolvedMutualSSL *dpv1alpha1.MutualSSL) error {
-	var mutualSSL *dpv1alpha1.MutualSSLConfig
-	if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil {
-		mutualSSL = authentication.Spec.Default.AuthTypes.MutualSSL
-	} else if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil {
-		mutualSSL = authentication.Spec.Override.AuthTypes.MutualSSL
+func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha2.Authentication, resolvedMutualSSL *dpv1alpha2.MutualSSL) error {
+	var mutualSSL *dpv1alpha2.MutualSSLConfig
+	authSpec := SelectPolicy(&authentication.Spec.Override, &authentication.Spec.Default, nil, nil)
+	if authSpec.AuthTypes != nil {
+		mutualSSL = authSpec.AuthTypes.MutualSSL
 	}
+
 	if mutualSSL != nil {
 		resolvedCertificates, err := ResolveAllmTLSCertificates(ctx, mutualSSL, client, authentication.Namespace)
 		resolvedMutualSSL.Disabled = mutualSSL.Disabled
@@ -478,7 +478,7 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic
 }
 
 // ResolveAllmTLSCertificates resolves all mTLS certificates
-func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.MutualSSLConfig, client k8client.Client, namespace string) ([]string, error) {
+func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha2.MutualSSLConfig, client k8client.Client, namespace string) ([]string, error) {
 	var resolvedCertificates []string
 	var err error
 	var certificate string
@@ -490,13 +490,13 @@ func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.Mutua
 	}
 	if mutualSSL.ConfigMapRefs != nil {
 		for _, cert := range mutualSSL.ConfigMapRefs {
-			certificate, err = ResolveCertificate(ctx, client, namespace, nil, cert, nil)
+			certificate, err = ResolveCertificate(ctx, client, namespace, nil, ConvertRefConfigsV2ToV1(cert), nil)
 			resolvedCertificates = append(resolvedCertificates, certificate)
 		}
 	}
 	if mutualSSL.SecretRefs != nil {
 		for _, cert := range mutualSSL.SecretRefs {
-			certificate, err = ResolveCertificate(ctx, client, namespace, nil, nil, cert)
+			certificate, err = ResolveCertificate(ctx, client, namespace, nil, nil, ConvertRefConfigsV2ToV1(cert))
 			resolvedCertificates = append(resolvedCertificates, certificate)
 		}
 	}
diff --git a/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
new file mode 100644
index 000000000..f1e5242cf
--- /dev/null
+++ b/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml
@@ -0,0 +1,558 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.12.0
+  name: authentications.dp.wso2.com
+spec:
+  group: dp.wso2.com
+  names:
+    kind: Authentication
+    listKind: AuthenticationList
+    plural: authentications
+    singular: authentication
+  scope: Namespaced
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Authentication is the Schema for the authentications API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: AuthenticationSpec defines the desired state of Authentication
+            properties:
+              default:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              override:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              targetRef:
+                description: PolicyTargetReference identifies an API object to apply
+                  policy to. This should be used as part of Policy resources that
+                  can target Gateway API resources. For more information on how this
+                  policy attachment model works, and a sample Policy resource, refer
+                  to the policy attachment documentation for Gateway API.
+                properties:
+                  group:
+                    description: Group is the group of the target resource.
+                    maxLength: 253
+                    pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                    type: string
+                  kind:
+                    description: Kind is kind of the target resource.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                    type: string
+                  name:
+                    description: Name is the name of the target resource.
+                    maxLength: 253
+                    minLength: 1
+                    type: string
+                  namespace:
+                    description: Namespace is the namespace of the referent. When
+                      unspecified, the local namespace is inferred. Even when policy
+                      targets a resource in a different namespace, it MUST only apply
+                      to traffic originating from the same namespace as the policy.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                    type: string
+                required:
+                - group
+                - kind
+                - name
+                type: object
+            type: object
+          status:
+            description: AuthenticationStatus defines the observed state of Authentication
+            type: object
+        type: object
+    served: true
+    storage: false
+    subresources:
+      status: {}
+  - name: v1alpha2
+    schema:
+      openAPIV3Schema:
+        description: Authentication is the Schema for the authentications API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: AuthenticationSpec defines the desired state of Authentication
+            properties:
+              default:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      mtls:
+                        description: MutualSSL is to specify the features and certificates
+                          for mutual SSL
+                        properties:
+                          certificatesInline:
+                            description: CertificatesInline is the Inline Certificate
+                              entry
+                            items:
+                              type: string
+                            type: array
+                          configMapRefs:
+                            description: ConfigMapRefs denotes the reference to the
+                              ConfigMap that contains the Certificate
+                            items:
+                              description: RefConfig holds a config for a secret or
+                                a configmap
+                              properties:
+                                key:
+                                  description: Key of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                                name:
+                                  description: Name of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                              required:
+                              - key
+                              - name
+                              type: object
+                            type: array
+                          disabled:
+                            default: false
+                            description: Disabled is to disable mTLS authentication
+                            type: boolean
+                          required:
+                            default: optional
+                            description: Required indicates whether mutualSSL is mandatory
+                              or optional
+                            enum:
+                            - mandatory
+                            - optional
+                            type: string
+                          secretRefs:
+                            description: SecretRefs denotes the reference to the Secret
+                              that contains the Certificate
+                            items:
+                              description: RefConfig holds a config for a secret or
+                                a configmap
+                              properties:
+                                key:
+                                  description: Key of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                                name:
+                                  description: Name of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                              required:
+                              - key
+                              - name
+                              type: object
+                            type: array
+                        type: object
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              override:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      mtls:
+                        description: MutualSSL is to specify the features and certificates
+                          for mutual SSL
+                        properties:
+                          certificatesInline:
+                            description: CertificatesInline is the Inline Certificate
+                              entry
+                            items:
+                              type: string
+                            type: array
+                          configMapRefs:
+                            description: ConfigMapRefs denotes the reference to the
+                              ConfigMap that contains the Certificate
+                            items:
+                              description: RefConfig holds a config for a secret or
+                                a configmap
+                              properties:
+                                key:
+                                  description: Key of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                                name:
+                                  description: Name of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                              required:
+                              - key
+                              - name
+                              type: object
+                            type: array
+                          disabled:
+                            default: false
+                            description: Disabled is to disable mTLS authentication
+                            type: boolean
+                          required:
+                            default: optional
+                            description: Required indicates whether mutualSSL is mandatory
+                              or optional
+                            enum:
+                            - mandatory
+                            - optional
+                            type: string
+                          secretRefs:
+                            description: SecretRefs denotes the reference to the Secret
+                              that contains the Certificate
+                            items:
+                              description: RefConfig holds a config for a secret or
+                                a configmap
+                              properties:
+                                key:
+                                  description: Key of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                                name:
+                                  description: Name of the secret or configmap
+                                  minLength: 1
+                                  type: string
+                              required:
+                              - key
+                              - name
+                              type: object
+                            type: array
+                        type: object
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              targetRef:
+                description: PolicyTargetReference identifies an API object to apply
+                  policy to. This should be used as part of Policy resources that
+                  can target Gateway API resources. For more information on how this
+                  policy attachment model works, and a sample Policy resource, refer
+                  to the policy attachment documentation for Gateway API.
+                properties:
+                  group:
+                    description: Group is the group of the target resource.
+                    maxLength: 253
+                    pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                    type: string
+                  kind:
+                    description: Kind is kind of the target resource.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                    type: string
+                  name:
+                    description: Name is the name of the target resource.
+                    maxLength: 253
+                    minLength: 1
+                    type: string
+                  namespace:
+                    description: Namespace is the namespace of the referent. When
+                      unspecified, the local namespace is inferred. Even when policy
+                      targets a resource in a different namespace, it MUST only apply
+                      to traffic originating from the same namespace as the policy.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                    type: string
+                required:
+                - group
+                - kind
+                - name
+                type: object
+            type: object
+          status:
+            description: AuthenticationStatus defines the observed state of Authentication
+            type: object
+        type: object
+    served: true
+    storage: true
+    subresources:
+      status: {}
diff --git a/common-controller/internal/operator/config/crd/kustomization.yaml b/common-controller/internal/operator/config/crd/kustomization.yaml
index 16ac3fc02..460c451ae 100644
--- a/common-controller/internal/operator/config/crd/kustomization.yaml
+++ b/common-controller/internal/operator/config/crd/kustomization.yaml
@@ -7,6 +7,7 @@ resources:
 - bases/cp.wso2.com_applications.yaml
 - bases/cp.wso2.com_subscriptions.yaml
 - bases/cp.wso2.com_applicationmappings.yaml
+- bases/dp.wso2.com_authentications.yaml
 #+kubebuilder:scaffold:crdkustomizeresource
 
 patches:
diff --git a/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml b/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml
new file mode 100644
index 000000000..680a50baf
--- /dev/null
+++ b/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml
@@ -0,0 +1,7 @@
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: authentications.dp.wso2.com
diff --git a/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml b/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml
new file mode 100644
index 000000000..a0c816328
--- /dev/null
+++ b/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml
@@ -0,0 +1,16 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: authentications.dp.wso2.com
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml b/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml
new file mode 100644
index 000000000..4d3e0f752
--- /dev/null
+++ b/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml
@@ -0,0 +1,31 @@
+# permissions for end users to edit authentications.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  labels:
+    app.kubernetes.io/name: clusterrole
+    app.kubernetes.io/instance: authentication-editor-role
+    app.kubernetes.io/component: rbac
+    app.kubernetes.io/created-by: operator
+    app.kubernetes.io/part-of: operator
+    app.kubernetes.io/managed-by: kustomize
+  name: authentication-editor-role
+rules:
+- apiGroups:
+  - dp.wso2.com
+  resources:
+  - authentications
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - dp.wso2.com
+  resources:
+  - authentications/status
+  verbs:
+  - get
diff --git a/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml b/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml
new file mode 100644
index 000000000..ab69c164c
--- /dev/null
+++ b/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml
@@ -0,0 +1,27 @@
+# permissions for end users to view authentications.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  labels:
+    app.kubernetes.io/name: clusterrole
+    app.kubernetes.io/instance: authentication-viewer-role
+    app.kubernetes.io/component: rbac
+    app.kubernetes.io/created-by: operator
+    app.kubernetes.io/part-of: operator
+    app.kubernetes.io/managed-by: kustomize
+  name: authentication-viewer-role
+rules:
+- apiGroups:
+  - dp.wso2.com
+  resources:
+  - authentications
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - dp.wso2.com
+  resources:
+  - authentications/status
+  verbs:
+  - get
diff --git a/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml b/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml
new file mode 100644
index 000000000..7c1486aeb
--- /dev/null
+++ b/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml
@@ -0,0 +1,12 @@
+apiVersion: dp.wso2.com/v1alpha2
+kind: Authentication
+metadata:
+  labels:
+    app.kubernetes.io/name: authentication
+    app.kubernetes.io/instance: authentication-sample
+    app.kubernetes.io/part-of: operator
+    app.kubernetes.io/managed-by: kustomize
+    app.kubernetes.io/created-by: operator
+  name: authentication-sample
+spec:
+  # TODO(user): Add fields here
diff --git a/common-controller/internal/operator/config/webhook/manifests.yaml b/common-controller/internal/operator/config/webhook/manifests.yaml
index 7d86cb224..411ed6ee8 100644
--- a/common-controller/internal/operator/config/webhook/manifests.yaml
+++ b/common-controller/internal/operator/config/webhook/manifests.yaml
@@ -44,6 +44,26 @@ webhooks:
     resources:
     - apipolicies
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: mauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
@@ -210,6 +230,26 @@ webhooks:
     resources:
     - apipolicies
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: vauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
diff --git a/common-controller/internal/operator/operator.go b/common-controller/internal/operator/operator.go
index d3414c534..73a252074 100644
--- a/common-controller/internal/operator/operator.go
+++ b/common-controller/internal/operator/operator.go
@@ -121,7 +121,7 @@ func InitOperator() {
 			"Unable to create webhook for APIPolicy, error: %v", err))
 	}
 
-	if err = (&dpv1alpha1.Authentication{}).SetupWebhookWithManager(mgr); err != nil {
+	if err = (&dpv1alpha2.Authentication{}).SetupWebhookWithManager(mgr); err != nil {
 		loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2638, logging.MAJOR,
 			"Unable to create webhook for Authentication, error: %v", err))
 	}
diff --git a/common-go-libs/PROJECT b/common-go-libs/PROJECT
index cb1f5622f..51763f3fd 100644
--- a/common-go-libs/PROJECT
+++ b/common-go-libs/PROJECT
@@ -32,6 +32,7 @@ resources:
   path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1
   version: v1alpha1
   webhooks:
+    conversion: true
     defaulting: true
     validation: true
     webhookVersion: v1
@@ -145,4 +146,17 @@ resources:
   kind: TokenIssuer
   path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2
   version: v1alpha2
+- api:
+    crdVersion: v1
+    namespaced: true
+  domain: wso2.com
+  group: dp
+  kind: Authentication
+  path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2
+  version: v1alpha2
+  webhooks:
+    conversion: true
+    defaulting: true
+    validation: true
+    webhookVersion: v1
 version: "3"
diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go
new file mode 100644
index 000000000..dd98f8ecc
--- /dev/null
+++ b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go
@@ -0,0 +1,86 @@
+/*
+ *  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"
+)
+
+// ConvertTo converts this Authentication CR to the Hub version (v1alpha2).
+// src is v1alpha1.Authentication and dst is v1alpha2.Authentication.
+func (src *Authentication) ConvertTo(dstRaw conversion.Hub) error {
+
+	dst := dstRaw.(*v1alpha2.Authentication)
+	dst.ObjectMeta = src.ObjectMeta
+
+	// Spec
+	dst.Spec.TargetRef = src.Spec.TargetRef
+
+	dst.Spec.Default.Disabled = src.Spec.Default.Disabled
+	dst.Spec.Override.Disabled = src.Spec.Override.Disabled
+
+	// Convert Oauth2Auth to v1alpha2.Oauth2Auth
+	dst.Spec.Default.AuthTypes.Oauth2 = v1alpha2.Oauth2Auth(src.Spec.Default.AuthTypes.Oauth2)
+	dst.Spec.Override.AuthTypes.Oauth2 = v1alpha2.Oauth2Auth(src.Spec.Override.AuthTypes.Oauth2)
+
+	for _, apiKeyAuth := range src.Spec.Default.AuthTypes.APIKey {
+		convertedAPIKeyAuth := v1alpha2.APIKeyAuth(apiKeyAuth)
+		dst.Spec.Default.AuthTypes.APIKey = append(dst.Spec.Default.AuthTypes.APIKey, convertedAPIKeyAuth)
+	}
+
+	for _, apiKeyAuth := range src.Spec.Override.AuthTypes.APIKey {
+		convertedAPIKeyAuth := v1alpha2.APIKeyAuth(apiKeyAuth)
+		dst.Spec.Override.AuthTypes.APIKey = append(dst.Spec.Override.AuthTypes.APIKey, convertedAPIKeyAuth)
+	}
+
+	// Status
+	dst.Status = v1alpha2.AuthenticationStatus(src.Status)
+
+	return nil
+}
+
+// ConvertFrom converts from the Hub version (v1alpha2) to this version.
+// src is v1alpha1.Authentication and dst is v1alpha2.Authentication.
+func (src *Authentication) ConvertFrom(srcRaw conversion.Hub) error {
+
+	dst := srcRaw.(*v1alpha2.Authentication)
+	src.ObjectMeta = dst.ObjectMeta
+
+	// Spec
+	src.Spec.TargetRef = dst.Spec.TargetRef
+
+	src.Spec.Default.Disabled = dst.Spec.Default.Disabled
+	src.Spec.Override.Disabled = dst.Spec.Override.Disabled
+	src.Spec.Default.AuthTypes.Oauth2 = Oauth2Auth(dst.Spec.Default.AuthTypes.Oauth2)
+	src.Spec.Override.AuthTypes.Oauth2 = Oauth2Auth(dst.Spec.Override.AuthTypes.Oauth2)
+
+	for _, apiKeyAuth := range dst.Spec.Default.AuthTypes.APIKey {
+		convertedAPIKeyAuth := APIKeyAuth(apiKeyAuth)
+		src.Spec.Default.AuthTypes.APIKey = append(src.Spec.Default.AuthTypes.APIKey, convertedAPIKeyAuth)
+	}
+
+	for _, apiKeyAuth := range dst.Spec.Override.AuthTypes.APIKey {
+		convertedAPIKeyAuth := APIKeyAuth(apiKeyAuth)
+		src.Spec.Override.AuthTypes.APIKey = append(src.Spec.Override.AuthTypes.APIKey, convertedAPIKeyAuth)
+	}
+
+	// Status
+	src.Status = AuthenticationStatus(dst.Status)
+	return nil
+}
diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go
index 6bdf75db5..55da2c21b 100644
--- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go
+++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go
@@ -57,36 +57,6 @@ type APIAuth struct {
 	//
 	// +optional
 	TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"`
-
-	// MutualSSL is to specify the features and certificates for mutual SSL
-	//
-	// +optional
-	MutualSSL *MutualSSLConfig `json:"mtls,omitempty"`
-}
-
-// MutualSSLConfig scheme type and details
-type MutualSSLConfig struct {
-
-	// Disabled is to disable mTLS authentication
-	//
-	// +kubebuilder:default:=false
-	// +optional
-	Disabled bool `json:"disabled,omitempty"`
-
-	// Required indicates whether mutualSSL is mandatory or optional
-	// +kubebuilder:validation:Enum=mandatory;optional
-	// +kubebuilder:default=optional
-	// +optional
-	Required string `json:"required"`
-
-	// CertificatesInline is the Inline Certificate entry
-	CertificatesInline []*string `json:"certificatesInline,omitempty"`
-
-	// SecretRefs denotes the reference to the Secret that contains the Certificate
-	SecretRefs []*RefConfig `json:"secretRefs,omitempty"`
-
-	// ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate
-	ConfigMapRefs []*RefConfig `json:"configMapRefs,omitempty"`
 }
 
 // TestConsoleKeyAuth Test Console Key Authentication scheme details
diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
index fb3f69747..0eefa868f 100644
--- a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
+++ b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go
@@ -18,8 +18,6 @@
 package v1alpha1
 
 import (
-	"strings"
-
 	constants "github.com/wso2/apk/common-go-libs/constants"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -67,9 +65,6 @@ func (r *Authentication) ValidateUpdate(old runtime.Object) (admission.Warnings,
 // ValidateAuthentication validates the Authentication
 func (r *Authentication) ValidateAuthentication() error {
 	var allErrs field.ErrorList
-	isOAuthDisabled := false
-	isMTLSMandatory := false
-	isMTLSDisabled := false
 
 	if r.Spec.TargetRef.Name == "" {
 		allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("targetRef").Child("name"), "Name is required"))
@@ -78,39 +73,6 @@ func (r *Authentication) ValidateAuthentication() error {
 		allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind,
 			"Invalid Kind is provided"))
 	}
-	var mutualSSL *MutualSSLConfig
-
-	if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil {
-		isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled
-		mutualSSL = r.Spec.Default.AuthTypes.MutualSSL
-
-		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
-		isMTLSDisabled = mutualSSL.Disabled
-		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes,
-				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
-		}
-		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL,
-				"invalid mTLS configuration - certificates not provided"))
-		}
-
-	} else if r.Spec.Override != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil {
-		isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled
-		mutualSSL = r.Spec.Override.AuthTypes.MutualSSL
-
-		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
-		isMTLSDisabled = mutualSSL.Disabled
-		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes,
-				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
-		}
-
-		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
-			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes.MutualSSL,
-				"invalid mTLS configuration - certificates not provided"))
-		}
-	}
 
 	if len(allErrs) > 0 {
 		return apierrors.NewInvalid(
diff --git a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go
index a82496ccf..60b8ac15b 100644
--- a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go
+++ b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go
@@ -64,11 +64,6 @@ func (in *APIAuth) DeepCopyInto(out *APIAuth) {
 		copy(*out, *in)
 	}
 	out.TestConsoleKey = in.TestConsoleKey
-	if in.MutualSSL != nil {
-		in, out := &in.MutualSSL, &out.MutualSSL
-		*out = new(MutualSSLConfig)
-		(*in).DeepCopyInto(*out)
-	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIAuth.
@@ -1045,74 +1040,6 @@ func (in JWTIssuerMapping) DeepCopy() JWTIssuerMapping {
 	return *out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *MutualSSL) DeepCopyInto(out *MutualSSL) {
-	*out = *in
-	if in.ClientCertificates != nil {
-		in, out := &in.ClientCertificates, &out.ClientCertificates
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSL.
-func (in *MutualSSL) DeepCopy() *MutualSSL {
-	if in == nil {
-		return nil
-	}
-	out := new(MutualSSL)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) {
-	*out = *in
-	if in.CertificatesInline != nil {
-		in, out := &in.CertificatesInline, &out.CertificatesInline
-		*out = make([]*string, len(*in))
-		for i := range *in {
-			if (*in)[i] != nil {
-				in, out := &(*in)[i], &(*out)[i]
-				*out = new(string)
-				**out = **in
-			}
-		}
-	}
-	if in.SecretRefs != nil {
-		in, out := &in.SecretRefs, &out.SecretRefs
-		*out = make([]*RefConfig, len(*in))
-		for i := range *in {
-			if (*in)[i] != nil {
-				in, out := &(*in)[i], &(*out)[i]
-				*out = new(RefConfig)
-				**out = **in
-			}
-		}
-	}
-	if in.ConfigMapRefs != nil {
-		in, out := &in.ConfigMapRefs, &out.ConfigMapRefs
-		*out = make([]*RefConfig, len(*in))
-		for i := range *in {
-			if (*in)[i] != nil {
-				in, out := &(*in)[i], &(*out)[i]
-				*out = new(RefConfig)
-				**out = **in
-			}
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSLConfig.
-func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig {
-	if in == nil {
-		return nil
-	}
-	out := new(MutualSSLConfig)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Oauth2Auth) DeepCopyInto(out *Oauth2Auth) {
 	*out = *in
diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go b/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go
new file mode 100644
index 000000000..a225d4895
--- /dev/null
+++ b/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go
@@ -0,0 +1,21 @@
+/*
+ *  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 v1alpha2
+
+// Hub marks this type as a conversion hub.
+func (*Authentication) Hub() {}
diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_types.go b/common-go-libs/apis/dp/v1alpha2/authentication_types.go
new file mode 100644
index 000000000..68abe7b97
--- /dev/null
+++ b/common-go-libs/apis/dp/v1alpha2/authentication_types.go
@@ -0,0 +1,178 @@
+/*
+ *  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 v1alpha2
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1alpha2"
+)
+
+// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
+// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
+
+// AuthenticationSpec defines the desired state of Authentication
+type AuthenticationSpec struct {
+	Default   *AuthSpec                       `json:"default,omitempty"`
+	Override  *AuthSpec                       `json:"override,omitempty"`
+	TargetRef gwapiv1b1.PolicyTargetReference `json:"targetRef,omitempty"`
+}
+
+// AuthSpec specification of the authentication service
+type AuthSpec struct {
+	// Disabled is to disable all authentications
+	Disabled *bool `json:"disabled,omitempty"`
+
+	// AuthTypes is to specify the authentication scheme types and details
+	AuthTypes *APIAuth `json:"authTypes,omitempty"`
+}
+
+// APIAuth Authentication scheme type and details
+type APIAuth struct {
+	// Oauth2 is to specify the Oauth2 authentication scheme details
+	//
+	// +optional
+	Oauth2 Oauth2Auth `json:"oauth2,omitempty"`
+
+	// APIKey is to specify the APIKey authentication scheme details
+	//
+	// +optional
+	// +nullable
+	APIKey []APIKeyAuth `json:"apiKey,omitempty"`
+
+	// TestConsoleKey is to specify the Test Console Key authentication scheme details
+	//
+	// +optional
+	TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"`
+
+	// MutualSSL is to specify the features and certificates for mutual SSL
+	//
+	// +optional
+	MutualSSL *MutualSSLConfig `json:"mtls,omitempty"`
+}
+
+// MutualSSLConfig scheme type and details
+type MutualSSLConfig struct {
+
+	// Disabled is to disable mTLS authentication
+	//
+	// +kubebuilder:default=false
+	// +optional
+	Disabled bool `json:"disabled,omitempty"`
+
+	// Required indicates whether mutualSSL is mandatory or optional
+	// +kubebuilder:validation:Enum=mandatory;optional
+	// +kubebuilder:default=optional
+	// +optional
+	Required string `json:"required"`
+
+	// CertificatesInline is the Inline Certificate entry
+	CertificatesInline []*string `json:"certificatesInline,omitempty"`
+
+	// SecretRefs denotes the reference to the Secret that contains the Certificate
+	SecretRefs []*RefConfig `json:"secretRefs,omitempty"`
+
+	// ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate
+	ConfigMapRefs []*RefConfig `json:"configMapRefs,omitempty"`
+}
+
+// TestConsoleKeyAuth Test Console Key Authentication scheme details
+type TestConsoleKeyAuth struct {
+	// Header is the header name used to pass the Test Console Key
+	//
+	// +kubebuilder:default:=internal-key
+	// +optional
+	// +kubebuilder:validation:MinLength=1
+	Header string `json:"header,omitempty"`
+
+	// SendTokenToUpstream is to specify whether the Test Console Key should be sent to the upstream
+	//
+	// +optional
+	SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"`
+}
+
+// Oauth2Auth OAuth2 Authentication scheme details
+type Oauth2Auth struct {
+
+	// Disabled is to disable OAuth2 authentication
+	//
+	// +kubebuilder:default=false
+	// +optional
+	Disabled bool `json:"disabled"`
+
+	// Header is the header name used to pass the OAuth2 token
+	//
+	// +kubebuilder:default=authorization
+	// +optional
+	Header string `json:"header,omitempty"`
+
+	// SendTokenToUpstream is to specify whether the OAuth2 token should be sent to the upstream
+	//
+	// +optional
+	SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"`
+}
+
+// APIKeyAuth APIKey Authentication scheme details
+type APIKeyAuth struct {
+	//  In is to specify how the APIKey is passed to the request
+	//
+	// +kubebuilder:validation:Enum=Header;Query
+	// +kubebuilder:validation:MinLength=1
+	In string `json:"in,omitempty"`
+
+	// Name is the name of the header or query parameter to be used
+	// +kubebuilder:validation:MinLength=1
+	Name string `json:"name,omitempty"`
+
+	// SendTokenToUpstream is to specify whether the APIKey should be sent to the upstream
+	//
+	// +optional
+	SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"`
+}
+
+// AuthenticationStatus defines the observed state of Authentication
+type AuthenticationStatus struct {
+	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +genclient
+//+kubebuilder:object:root=true
+//+kubebuilder:subresource:status
+//+kubebuilder:storageversion
+
+// Authentication is the Schema for the authentications API
+type Authentication struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   AuthenticationSpec   `json:"spec,omitempty"`
+	Status AuthenticationStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// AuthenticationList contains a list of Authentication
+type AuthenticationList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Authentication `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&Authentication{}, &AuthenticationList{})
+}
diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go
new file mode 100644
index 000000000..56fe74e0e
--- /dev/null
+++ b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go
@@ -0,0 +1,126 @@
+/*
+ *  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 v1alpha2
+
+import (
+	"strings"
+
+	constants "github.com/wso2/apk/common-go-libs/constants"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/util/validation/field"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+)
+
+func (r *Authentication) SetupWebhookWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewWebhookManagedBy(mgr).
+		For(r).
+		Complete()
+}
+
+// TODO(user): EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
+
+//+kubebuilder:webhook:path=/mutate-dp-wso2-com-v1alpha2-authentication,mutating=true,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha2,name=mauthentication.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Defaulter = &Authentication{}
+
+// Default implements webhook.Defaulter so a webhook will be registered for the type
+func (r *Authentication) Default() {
+	// TODO(user): fill in your defaulting logic.
+}
+
+// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
+//+kubebuilder:webhook:path=/validate-dp-wso2-com-v1alpha2-authentication,mutating=false,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha2,name=vauthentication.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Validator = &Authentication{}
+
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
+func (r *Authentication) ValidateCreate() (admission.Warnings, error) {
+	// TODO(user): fill in your validation logic upon object creation.
+	return nil, r.ValidateAuthentication()
+}
+
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
+func (r *Authentication) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
+	return nil, r.ValidateAuthentication()
+}
+
+// ValidateAuthentication validates the Authentication
+func (r *Authentication) ValidateAuthentication() error {
+	var allErrs field.ErrorList
+	isOAuthDisabled := false
+	isMTLSMandatory := false
+	isMTLSDisabled := false
+
+	if r.Spec.TargetRef.Name == "" {
+		allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("targetRef").Child("name"), "Name is required"))
+	}
+	if !(r.Spec.TargetRef.Kind == constants.KindAPI || r.Spec.TargetRef.Kind == constants.KindResource) {
+		allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind,
+			"Invalid Kind is provided"))
+	}
+	var mutualSSL *MutualSSLConfig
+
+	if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil {
+		isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled
+		mutualSSL = r.Spec.Default.AuthTypes.MutualSSL
+
+		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
+		isMTLSDisabled = mutualSSL.Disabled
+		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes,
+				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
+		}
+		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL,
+				"invalid mTLS configuration - certificates not provided"))
+		}
+
+	} else if r.Spec.Override != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil {
+		isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled
+		mutualSSL = r.Spec.Override.AuthTypes.MutualSSL
+
+		isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory"
+		isMTLSDisabled = mutualSSL.Disabled
+		if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes,
+				"invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory"))
+		}
+
+		if len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 {
+			allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes.MutualSSL,
+				"invalid mTLS configuration - certificates not provided"))
+		}
+	}
+
+	if len(allErrs) > 0 {
+		return apierrors.NewInvalid(
+			schema.GroupKind{Group: "dp.wso2.com", Kind: "Authentication"},
+			r.Name, allErrs)
+	}
+	return nil
+}
+
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
+func (r *Authentication) ValidateDelete() (admission.Warnings, error) {
+	// TODO(user): fill in your validation logic upon object deletion.
+	return nil, nil
+}
diff --git a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go b/common-go-libs/apis/dp/v1alpha2/mutualSSL.go
similarity index 90%
rename from common-go-libs/apis/dp/v1alpha1/mutualSSL.go
rename to common-go-libs/apis/dp/v1alpha2/mutualSSL.go
index 96485a159..54e21c54c 100644
--- a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go
+++ b/common-go-libs/apis/dp/v1alpha2/mutualSSL.go
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
+ *  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.
@@ -15,7 +15,7 @@
  *
  */
 
-package v1alpha1
+package v1alpha2
 
 // MutualSSL defines the mutual SSL configurations for an API
 type MutualSSL struct {
diff --git a/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go b/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go
index a43cff45a..d9905b38b 100644
--- a/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go
+++ b/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go
@@ -103,6 +103,9 @@ var _ = BeforeSuite(func() {
 	err = (&APIPolicy{}).SetupWebhookWithManager(mgr)
 	Expect(err).NotTo(HaveOccurred())
 
+	err = (&Authentication{}).SetupWebhookWithManager(mgr)
+	Expect(err).NotTo(HaveOccurred())
+
 	//+kubebuilder:scaffold:webhook
 
 	go func() {
diff --git a/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go
index 4bd94c66e..9f683a179 100644
--- a/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go
+++ b/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go
@@ -55,6 +55,48 @@ func (in *API) DeepCopyObject() runtime.Object {
 	return nil
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *APIAuth) DeepCopyInto(out *APIAuth) {
+	*out = *in
+	out.Oauth2 = in.Oauth2
+	if in.APIKey != nil {
+		in, out := &in.APIKey, &out.APIKey
+		*out = make([]APIKeyAuth, len(*in))
+		copy(*out, *in)
+	}
+	out.TestConsoleKey = in.TestConsoleKey
+	if in.MutualSSL != nil {
+		in, out := &in.MutualSSL, &out.MutualSSL
+		*out = new(MutualSSLConfig)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIAuth.
+func (in *APIAuth) DeepCopy() *APIAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(APIAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *APIKeyAuth) DeepCopyInto(out *APIKeyAuth) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIKeyAuth.
+func (in *APIKeyAuth) DeepCopy() *APIKeyAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(APIKeyAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *APIList) DeepCopyInto(out *APIList) {
 	*out = *in
@@ -237,6 +279,131 @@ func (in *APIStatus) DeepCopy() *APIStatus {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthSpec) DeepCopyInto(out *AuthSpec) {
+	*out = *in
+	if in.Disabled != nil {
+		in, out := &in.Disabled, &out.Disabled
+		*out = new(bool)
+		**out = **in
+	}
+	if in.AuthTypes != nil {
+		in, out := &in.AuthTypes, &out.AuthTypes
+		*out = new(APIAuth)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSpec.
+func (in *AuthSpec) DeepCopy() *AuthSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Authentication) DeepCopyInto(out *Authentication) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication.
+func (in *Authentication) DeepCopy() *Authentication {
+	if in == nil {
+		return nil
+	}
+	out := new(Authentication)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Authentication) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthenticationList) DeepCopyInto(out *AuthenticationList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Authentication, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationList.
+func (in *AuthenticationList) DeepCopy() *AuthenticationList {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthenticationList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *AuthenticationList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthenticationSpec) DeepCopyInto(out *AuthenticationSpec) {
+	*out = *in
+	if in.Default != nil {
+		in, out := &in.Default, &out.Default
+		*out = new(AuthSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Override != nil {
+		in, out := &in.Override, &out.Override
+		*out = new(AuthSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	in.TargetRef.DeepCopyInto(&out.TargetRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationSpec.
+func (in *AuthenticationSpec) DeepCopy() *AuthenticationSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthenticationSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthenticationStatus) DeepCopyInto(out *AuthenticationStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationStatus.
+func (in *AuthenticationStatus) DeepCopy() *AuthenticationStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthenticationStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *BackendJWTToken) DeepCopyInto(out *BackendJWTToken) {
 	*out = *in
@@ -599,6 +766,89 @@ func (in *JWKS) DeepCopy() *JWKS {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MutualSSL) DeepCopyInto(out *MutualSSL) {
+	*out = *in
+	if in.ClientCertificates != nil {
+		in, out := &in.ClientCertificates, &out.ClientCertificates
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSL.
+func (in *MutualSSL) DeepCopy() *MutualSSL {
+	if in == nil {
+		return nil
+	}
+	out := new(MutualSSL)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) {
+	*out = *in
+	if in.CertificatesInline != nil {
+		in, out := &in.CertificatesInline, &out.CertificatesInline
+		*out = make([]*string, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(string)
+				**out = **in
+			}
+		}
+	}
+	if in.SecretRefs != nil {
+		in, out := &in.SecretRefs, &out.SecretRefs
+		*out = make([]*RefConfig, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(RefConfig)
+				**out = **in
+			}
+		}
+	}
+	if in.ConfigMapRefs != nil {
+		in, out := &in.ConfigMapRefs, &out.ConfigMapRefs
+		*out = make([]*RefConfig, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(RefConfig)
+				**out = **in
+			}
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSLConfig.
+func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(MutualSSLConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Oauth2Auth) DeepCopyInto(out *Oauth2Auth) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Oauth2Auth.
+func (in *Oauth2Auth) DeepCopy() *Oauth2Auth {
+	if in == nil {
+		return nil
+	}
+	out := new(Oauth2Auth)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PolicySpec) DeepCopyInto(out *PolicySpec) {
 	*out = *in
@@ -689,6 +939,21 @@ func (in *SignatureValidation) DeepCopy() *SignatureValidation {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TestConsoleKeyAuth) DeepCopyInto(out *TestConsoleKeyAuth) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestConsoleKeyAuth.
+func (in *TestConsoleKeyAuth) DeepCopy() *TestConsoleKeyAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(TestConsoleKeyAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TokenIssuer) DeepCopyInto(out *TokenIssuer) {
 	*out = *in
diff --git a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml
index fcb15768b..f1e5242cf 100644
--- a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml
+++ b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml
@@ -15,6 +15,214 @@ spec:
   scope: Namespaced
   versions:
   - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Authentication is the Schema for the authentications API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: AuthenticationSpec defines the desired state of Authentication
+            properties:
+              default:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              override:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              targetRef:
+                description: PolicyTargetReference identifies an API object to apply
+                  policy to. This should be used as part of Policy resources that
+                  can target Gateway API resources. For more information on how this
+                  policy attachment model works, and a sample Policy resource, refer
+                  to the policy attachment documentation for Gateway API.
+                properties:
+                  group:
+                    description: Group is the group of the target resource.
+                    maxLength: 253
+                    pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                    type: string
+                  kind:
+                    description: Kind is kind of the target resource.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                    type: string
+                  name:
+                    description: Name is the name of the target resource.
+                    maxLength: 253
+                    minLength: 1
+                    type: string
+                  namespace:
+                    description: Namespace is the namespace of the referent. When
+                      unspecified, the local namespace is inferred. Even when policy
+                      targets a resource in a different namespace, it MUST only apply
+                      to traffic originating from the same namespace as the policy.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                    type: string
+                required:
+                - group
+                - kind
+                - name
+                type: object
+            type: object
+          status:
+            description: AuthenticationStatus defines the observed state of Authentication
+            type: object
+        type: object
+    served: true
+    storage: false
+    subresources:
+      status: {}
+  - name: v1alpha2
     schema:
       openAPIV3Schema:
         description: Authentication is the Schema for the authentications API
@@ -102,6 +310,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -128,8 +337,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
@@ -237,6 +444,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -263,8 +471,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
diff --git a/common-go-libs/config/webhook/manifests.yaml b/common-go-libs/config/webhook/manifests.yaml
index 7d86cb224..411ed6ee8 100644
--- a/common-go-libs/config/webhook/manifests.yaml
+++ b/common-go-libs/config/webhook/manifests.yaml
@@ -44,6 +44,26 @@ webhooks:
     resources:
     - apipolicies
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: mauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
@@ -210,6 +230,26 @@ webhooks:
     resources:
     - apipolicies
   sideEffects: None
+- admissionReviewVersions:
+  - v1
+  clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /validate-dp-wso2-com-v1alpha2-authentication
+  failurePolicy: Fail
+  name: vauthentication.kb.io
+  rules:
+  - apiGroups:
+    - dp.wso2.com
+    apiVersions:
+    - v1alpha2
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - authentications
+  sideEffects: None
 - admissionReviewVersions:
   - v1
   clientConfig:
diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java
index 4fc6ace7c..065016446 100644
--- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java
+++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java
@@ -105,10 +105,6 @@ public String init(Api api) {
             throw new SecurityException(e);
         }
 
-        for (Certificate certificate : api.getClientCertificatesList()) {
-            mtlsCertificateTiers.put(certificate.getAlias(), certificate.getTier());
-        }
-
         BackendJWTTokenInfo backendJWTTokenInfo = api.getBackendJWTTokenInfo();
         JWTConfigurationDto jwtConfigurationDto = new JWTConfigurationDto();
 
@@ -150,7 +146,7 @@ public String init(Api api) {
                 .resources(resources).apiType(apiType).apiLifeCycleState(apiLifeCycleState).tier(api.getTier())
                 .envType(api.getEnvType()).disableAuthentication(api.getDisableAuthentications())
                 .disableScopes(api.getDisableScopes()).trustStore(trustStore).organizationId(api.getOrganizationId())
-                .mtlsCertificateTiers(mtlsCertificateTiers).mutualSSL(mutualSSL)
+                .mutualSSL(mutualSSL)
                 .applicationSecurity(applicationSecurity).jwtConfigurationDto(jwtConfigurationDto)
                 .apiDefinition(apiDefinition).environment(api.getEnvironment())
                 .subscriptionValidation(api.getSubscriptionValidation()).graphQLSchemaDTO(graphQLSchemaDTO).build();
@@ -171,7 +167,8 @@ public ResponseObject process(RequestContext requestContext) {
         // This flag is used to apply CORS filter
         boolean isOptionCall = requestContext.getRequestMethod().contains(HttpConstants.OPTIONS);
 
-        // handle other not allowed && non option request && not yet handled error scenarios.
+        // handle other not allowed && non option request && not yet handled error
+        // scenarios.
         if ((!isOptionCall && !isExistsMatchedOperations) && !requestContext.getProperties()
                 .containsKey(APIConstants.MessageFormat.ERROR_CODE)) {
             requestContext.getProperties()
diff --git a/helm-charts/crds/dp.wso2.com_authentications.yaml b/helm-charts/crds/dp.wso2.com_authentications.yaml
index 1dbc523a5..f1e5242cf 100644
--- a/helm-charts/crds/dp.wso2.com_authentications.yaml
+++ b/helm-charts/crds/dp.wso2.com_authentications.yaml
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.9.2
-  creationTimestamp: null
+    controller-gen.kubebuilder.io/version: v0.12.0
   name: authentications.dp.wso2.com
 spec:
   group: dp.wso2.com
@@ -16,6 +15,214 @@ spec:
   scope: Namespaced
   versions:
   - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Authentication is the Schema for the authentications API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: AuthenticationSpec defines the desired state of Authentication
+            properties:
+              default:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              override:
+                description: AuthSpec specification of the authentication service
+                properties:
+                  authTypes:
+                    description: AuthTypes is to specify the authentication scheme
+                      types and details
+                    properties:
+                      apiKey:
+                        description: APIKey is to specify the APIKey authentication
+                          scheme details
+                        items:
+                          description: APIKeyAuth APIKey Authentication scheme details
+                          properties:
+                            in:
+                              description: In is to specify how the APIKey is passed
+                                to the request
+                              enum:
+                              - Header
+                              - Query
+                              minLength: 1
+                              type: string
+                            name:
+                              description: Name is the name of the header or query
+                                parameter to be used
+                              minLength: 1
+                              type: string
+                            sendTokenToUpstream:
+                              description: SendTokenToUpstream is to specify whether
+                                the APIKey should be sent to the upstream
+                              type: boolean
+                          type: object
+                        nullable: true
+                        type: array
+                      oauth2:
+                        description: Oauth2 is to specify the Oauth2 authentication
+                          scheme details
+                        properties:
+                          disabled:
+                            default: false
+                            description: Disabled is to disable OAuth2 authentication
+                            type: boolean
+                          header:
+                            default: authorization
+                            description: Header is the header name used to pass the
+                              OAuth2 token
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the OAuth2 token should be sent to the upstream
+                            type: boolean
+                        type: object
+                      testConsoleKey:
+                        description: TestConsoleKey is to specify the Test Console
+                          Key authentication scheme details
+                        properties:
+                          header:
+                            default: internal-key
+                            description: Header is the header name used to pass the
+                              Test Console Key
+                            minLength: 1
+                            type: string
+                          sendTokenToUpstream:
+                            description: SendTokenToUpstream is to specify whether
+                              the Test Console Key should be sent to the upstream
+                            type: boolean
+                        type: object
+                    type: object
+                  disabled:
+                    description: Disabled is to disable all authentications
+                    type: boolean
+                type: object
+              targetRef:
+                description: PolicyTargetReference identifies an API object to apply
+                  policy to. This should be used as part of Policy resources that
+                  can target Gateway API resources. For more information on how this
+                  policy attachment model works, and a sample Policy resource, refer
+                  to the policy attachment documentation for Gateway API.
+                properties:
+                  group:
+                    description: Group is the group of the target resource.
+                    maxLength: 253
+                    pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                    type: string
+                  kind:
+                    description: Kind is kind of the target resource.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
+                    type: string
+                  name:
+                    description: Name is the name of the target resource.
+                    maxLength: 253
+                    minLength: 1
+                    type: string
+                  namespace:
+                    description: Namespace is the namespace of the referent. When
+                      unspecified, the local namespace is inferred. Even when policy
+                      targets a resource in a different namespace, it MUST only apply
+                      to traffic originating from the same namespace as the policy.
+                    maxLength: 63
+                    minLength: 1
+                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                    type: string
+                required:
+                - group
+                - kind
+                - name
+                type: object
+            type: object
+          status:
+            description: AuthenticationStatus defines the observed state of Authentication
+            type: object
+        type: object
+    served: true
+    storage: false
+    subresources:
+      status: {}
+  - name: v1alpha2
     schema:
       openAPIV3Schema:
         description: Authentication is the Schema for the authentications API
@@ -103,6 +310,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -129,8 +337,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
@@ -238,6 +444,7 @@ spec:
                             description: Disabled is to disable mTLS authentication
                             type: boolean
                           required:
+                            default: optional
                             description: Required indicates whether mutualSSL is mandatory
                               or optional
                             enum:
@@ -264,8 +471,6 @@ spec:
                               - name
                               type: object
                             type: array
-                        required:
-                        - required
                         type: object
                       oauth2:
                         description: Oauth2 is to specify the Oauth2 authentication
diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml
index 229ef819d..6b30071c9 100644
--- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml
+++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml
@@ -64,19 +64,19 @@ webhooks:
         - apipolicies
   sideEffects: None
 - admissionReviewVersions:
-  - v1
+    - v1
   clientConfig:
     service:
       name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service
       namespace: {{ .Release.Namespace }}
-      path: /mutate-dp-wso2-com-v1alpha1-authentication
+      path: /mutate-dp-wso2-com-v1alpha2-authentication
   failurePolicy: Fail
   name: mauthentication.kb.io
   rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
-    - v1alpha1
+    - v1alpha2
     operations:
     - CREATE
     - UPDATE
diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml
index 0a2ca5d9c..5edc76ec9 100644
--- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml
+++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml
@@ -89,14 +89,14 @@ webhooks:
     service:
       name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service
       namespace: {{ .Release.Namespace }}
-      path: /validate-dp-wso2-com-v1alpha1-authentication
+      path: /validate-dp-wso2-com-v1alpha2-authentication
   failurePolicy: Fail
   name: vauthentication.kb.io
   rules:
   - apiGroups:
     - dp.wso2.com
     apiVersions:
-    - v1alpha1
+    - v1alpha2
     operations:
     - CREATE
     - UPDATE
diff --git a/runtime/config-deployer-service/ballerina/K8sClient.bal b/runtime/config-deployer-service/ballerina/K8sClient.bal
index e11aaefed..7dd1ff34f 100644
--- a/runtime/config-deployer-service/ballerina/K8sClient.bal
+++ b/runtime/config-deployer-service/ballerina/K8sClient.bal
@@ -61,21 +61,22 @@ isolated function deleteAPICR(string name, string namespace) returns http:Respon
 }
 
 isolated function deleteAuthenticationCR(string name, string namespace) returns http:Response|http:ClientError {
-    string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + name;
+    string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + name;
     return k8sApiServerEp->delete(endpoint, targetType = http:Response);
 }
+
 isolated function getAuthenticationCR(string name, string namespace) returns model:Authentication|http:ClientError {
-    string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + name;
+    string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:Authentication);
 }
 
 isolated function deployAuthenticationCR(model:Authentication authentication, string namespace) returns http:Response|http:ClientError {
-    string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications";
+    string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications";
     return k8sApiServerEp->post(endpoint, authentication, targetType = http:Response);
 }
 
 isolated function updateAuthenticationCR(model:Authentication authentication, string namespace) returns http:Response|http:ClientError {
-    string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + authentication.metadata.name;
+    string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + authentication.metadata.name;
     return k8sApiServerEp->put(endpoint, authentication, targetType = http:Response);
 }
 
@@ -93,6 +94,7 @@ isolated function getConfigMap(string name, string namespace) returns model:Conf
     string endpoint = "/api/v1/namespaces/" + namespace + "/configmaps/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:ConfigMap);
 }
+
 isolated function deleteConfigMap(string name, string namespace) returns http:Response|http:ClientError {
     string endpoint = "/api/v1/namespaces/" + namespace + "/configmaps/" + name;
     return k8sApiServerEp->delete(endpoint, targetType = http:Response);
@@ -169,6 +171,7 @@ isolated function getBackendCR(string name, string namespace) returns model:Back
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backends/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:Backend);
 }
+
 isolated function deployBackendCR(model:Backend backend, string namespace) returns http:Response|http:ClientError {
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backends";
     return k8sApiServerEp->post(endpoint, backend, targetType = http:Response);
@@ -231,6 +234,7 @@ isolated function getRateLimitPolicyCR(string name, string namespace) returns mo
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/ratelimitpolicies/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:RateLimitPolicy);
 }
+
 isolated function deleteRateLimitPolicyCR(string name, string namespace) returns http:Response|http:ClientError {
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/ratelimitpolicies/" + name;
     return k8sApiServerEp->delete(endpoint, targetType = http:Response);
@@ -280,6 +284,7 @@ isolated function getInterceptorServiceCR(string name, string namespace) returns
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/interceptorservices/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:InterceptorService);
 }
+
 isolated function deleteInterceptorServiceCR(string name, string namespace) returns http:Response|http:ClientError {
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/interceptorservices/" + name;
     return k8sApiServerEp->delete(endpoint, targetType = http:Response);
@@ -299,10 +304,12 @@ isolated function updateBackendJWTCr(model:BackendJWT backendJWT, string namespa
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + backendJWT.metadata.name;
     return k8sApiServerEp->put(endpoint, backendJWT, targetType = http:Response);
 }
+
 isolated function getBackendJWTCr(string name, string namespace) returns model:BackendJWT|http:ClientError {
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + name;
     return k8sApiServerEp->get(endpoint, targetType = model:BackendJWT);
 }
+
 isolated function deleteBackendJWTCr(string name, string namespace) returns http:Response|http:ClientError {
     string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + name;
     return k8sApiServerEp->delete(endpoint, targetType = http:Response);
diff --git a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal
index 7fc022be4..4220e5e8d 100644
--- a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal
+++ b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal
@@ -16,7 +16,7 @@
 // under the License.
 //
 public type Authentication record {
-    string apiVersion = "dp.wso2.com/v1alpha1";
+    string apiVersion = "dp.wso2.com/v1alpha2";
     string kind = "Authentication";
     Metadata metadata;
     AuthenticationSpec spec;
@@ -66,7 +66,7 @@ public type APIKey record {
 };
 
 public type AuthenticationList record {
-    string apiVersion = "dp.wso2.com/v1alpha1";
+    string apiVersion = "dp.wso2.com/v1alpha2";
     string kind = "AuthenticationList";
     Authentication[] items;
     ListMeta metadata;