From d13f6cdefaac6cc2f89b3ca8bafd09fd2b5c4bd6 Mon Sep 17 00:00:00 2001 From: tharindu1st Date: Tue, 12 Dec 2023 12:59:21 +0530 Subject: [PATCH 1/2] refactor-2 subscription --- .../cp/applicationmapping_controller.go | 35 +++-- .../enforcer/dto/APIKeyValidationInfoDTO.java | 22 +++ .../models/ApplicationKeyMapping.java | 16 +- .../apk/enforcer/security/KeyValidator.java | 47 +++--- .../security/jwt/JWTAuthenticator.java | 4 +- .../ApplicationKeyMappingDTO.java | 10 +- .../subscription/ApplicationMappingDto.java | 10 +- .../subscription/EventingGrpcClient.java | 21 ++- .../subscription/SubscriptionDataStore.java | 6 +- .../SubscriptionDataStoreImpl.java | 49 ++----- .../SubscriptionDataStoreUtil.java | 138 +++++++++++++----- .../gateway-components/common-log-conf.yaml | 41 ++++++ test/cucumber-tests/CRs/artifacts.yaml | 85 +++++++++++ .../integration/api/JWTGeneratorSteps.java | 24 +++ .../artifacts/apk-confs/subscription-api.yaml | 27 ++++ .../tests/api/APISubscription.feature | 72 +++++++++ 16 files changed, 466 insertions(+), 141 deletions(-) create mode 100644 test/cucumber-tests/src/test/resources/artifacts/apk-confs/subscription-api.yaml create mode 100644 test/cucumber-tests/src/test/resources/tests/api/APISubscription.feature diff --git a/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go b/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go index c24c71466..9599f0b11 100644 --- a/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go +++ b/common-controller/internal/operator/controllers/cp/applicationmapping_controller.go @@ -117,29 +117,32 @@ func (r *ApplicationMappingReconciler) Reconcile(ctx context.Context, req ctrl.R var applicationMapping cpv1alpha2.ApplicationMapping if err := r.client.Get(ctx, req.NamespacedName, &applicationMapping); err != nil { if k8error.IsNotFound(err) { + loggers.LoggerAPKOperator.Debugf("Application mapping %s/%s not found in k8s", applicationMappingKey.Namespace, applicationMappingKey.Name) applicationMapping, found := r.ods.GetApplicationMappingFromStore(applicationMappingKey) if found { + loggers.LoggerAPKOperator.Debugf("Application mapping %s/%s found in operator data store. Deleting from operator data store and sending delete event to server", applicationMappingKey.Namespace, applicationMappingKey.Name) utils.SendDeleteApplicationMappingEvent(applicationMappingKey.Name, applicationMapping) r.ods.DeleteApplicationMappingFromStore(applicationMappingKey) server.DeleteApplicationMapping(applicationMappingKey.Name) } else { loggers.LoggerAPKOperator.Debugf("Application mapping %s/%s not found. Ignoring since object must be deleted", applicationMappingKey.Namespace, applicationMappingKey.Name) } - } else { - var application cpv1alpha2.Application - if err := r.client.Get(ctx, types.NamespacedName{Name: string(applicationMapping.Spec.ApplicationRef), Namespace: applicationMapping.Namespace}, &application); err != nil { - loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2614, logging.BLOCKER, "Error getting Application: %v", err)) - return ctrl.Result{}, nil - } - var subscription cpv1alpha2.Subscription - if err := r.client.Get(ctx, types.NamespacedName{Name: string(applicationMapping.Spec.SubscriptionRef), Namespace: applicationMapping.Namespace}, &subscription); err != nil { - loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2615, logging.BLOCKER, "Error getting Subscription: %v", err)) - return ctrl.Result{}, nil - } - sendUpdates(&applicationMapping, application, subscription) - utils.SendCreateApplicationMappingEvent(applicationMapping, application, subscription) - r.ods.AddorUpdateApplicationMappingToStore(applicationMappingKey, applicationMapping.Spec) } + } else { + var application cpv1alpha2.Application + if err := r.client.Get(ctx, types.NamespacedName{Name: string(applicationMapping.Spec.ApplicationRef), Namespace: applicationMapping.Namespace}, &application); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2614, logging.CRITICAL, "Error getting Application: %v", err)) + return ctrl.Result{}, nil + } + var subscription cpv1alpha2.Subscription + if err := r.client.Get(ctx, types.NamespacedName{Name: string(applicationMapping.Spec.SubscriptionRef), Namespace: applicationMapping.Namespace}, &subscription); err != nil { + loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2615, logging.CRITICAL, "Error getting Subscription: %v", err)) + return ctrl.Result{}, nil + } + loggers.LoggerAPKOperator.Debugf("Reconsile completed Application mapping :%v,Subscription %v application : %v", applicationMapping, subscription, application) + sendUpdates(&applicationMapping, application, subscription) + utils.SendCreateApplicationMappingEvent(applicationMapping, application, subscription) + r.ods.AddorUpdateApplicationMappingToStore(applicationMappingKey, applicationMapping.Spec) } return ctrl.Result{}, nil } @@ -220,7 +223,7 @@ func (r *ApplicationMappingReconciler) getApplicationMappingsForApplication(ctx Namespace: applicationMapping.Namespace}, } requests = append(requests, req) - loggers.LoggerAPKOperator.Infof("Adding reconcile request for ApplicationMapping: %s/%s with Application UUID: %v", applicationMapping.Namespace, applicationMapping.Name, + loggers.LoggerAPKOperator.Debugf("Adding reconcile request for ApplicationMapping: %s/%s with Application UUID: %v", applicationMapping.Namespace, applicationMapping.Name, string(applicationMapping.ObjectMeta.UID)) } return requests @@ -256,7 +259,7 @@ func (r *ApplicationMappingReconciler) getApplicationMappingsForSubscription(ctx Namespace: applicationMapping.Namespace}, } requests = append(requests, req) - loggers.LoggerAPKOperator.Infof("Adding reconcile request for ApplicationMapping: %s/%s with Subscription UUID: %v", applicationMapping.Namespace, applicationMapping.Name, + loggers.LoggerAPKOperator.Debugf("Adding reconcile request for ApplicationMapping: %s/%s with Subscription UUID: %v", applicationMapping.Namespace, applicationMapping.Name, string(applicationMapping.ObjectMeta.UID)) } return requests diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/dto/APIKeyValidationInfoDTO.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/dto/APIKeyValidationInfoDTO.java index 8f4342809..99db9c3ad 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/dto/APIKeyValidationInfoDTO.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/dto/APIKeyValidationInfoDTO.java @@ -66,6 +66,8 @@ public class APIKeyValidationInfoDTO implements Serializable { private String apiContext; private String applicationUUID; private Map appAttributes; + private String envType; + private String environment; public String getOrganization() { @@ -431,5 +433,25 @@ public void setApiUUID(String apiUUID) { this.apiUUID = apiUUID; } + + public void setEnvType(String envType) { + + this.envType = envType; + } + + public String getEnvType() { + + return envType; + } + + public void setEnvironment(String environment) { + + this.environment = environment; + } + + public String getEnvironment() { + + return environment; + } } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/ApplicationKeyMapping.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/ApplicationKeyMapping.java index aadc9f92e..e9777c537 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/ApplicationKeyMapping.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/models/ApplicationKeyMapping.java @@ -19,6 +19,7 @@ package org.wso2.apk.enforcer.models; import org.wso2.apk.enforcer.common.CacheableEntity; +import org.wso2.apk.enforcer.subscription.SubscriptionDataStoreUtil; /** * Entity for keeping mapping between Application and Consumer key. @@ -32,52 +33,65 @@ public class ApplicationKeyMapping implements CacheableEntity { private String envId; public String getApplicationUUID() { + return applicationUUID; } public void setApplicationUUID(String applicationUUID) { + this.applicationUUID = applicationUUID; } public String getSecurityScheme() { + return securityScheme; } public void setSecurityScheme(String securityScheme) { + this.securityScheme = securityScheme; } public String getApplicationIdentifier() { + return applicationIdentifier; } public void setApplicationIdentifier(String applicationIdentifier) { + this.applicationIdentifier = applicationIdentifier; } public String getKeyType() { + return keyType; } public void setKeyType(String keyType) { + this.keyType = keyType; } public String getEnvId() { + return envId; } public void setEnvId(String envId) { + this.envId = envId; } @Override public String getCacheKey() { - return securityScheme + CacheableEntity.DELEM_PERIOD + applicationIdentifier; + + return SubscriptionDataStoreUtil.getApplicationKeyMappingCacheKey(applicationIdentifier, keyType, + securityScheme, envId); } @Override public String toString() { + return "ApplicationKeyMapping{" + "applicationUUID='" + applicationUUID + '\'' + ", securityScheme='" + securityScheme + '\'' + diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/KeyValidator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/KeyValidator.java index 6ff936dfc..cdaefe83f 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/KeyValidator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/KeyValidator.java @@ -119,15 +119,15 @@ public static void validateSubscriptionUsingConsumerKey(APIKeyValidationInfoDTO throws APISecurityException { Application app; - Subscription sub; + Subscription sub = null; ApplicationKeyMapping keyMapping; - ApplicationMapping appMapping; + Set appMappings; String apiName = validationInfo.getApiName(); String apiContext = validationInfo.getApiContext(); String apiVersion = validationInfo.getApiVersion(); String consumerKey = validationInfo.getConsumerKey(); String securityScheme = validationInfo.getSecurityScheme(); - String keyType = validationInfo.getType(); + String keyType = validationInfo.getEnvType(); log.debug("Before validating subscriptions"); log.debug("Validation Info : { name : {}, context : {}, version : {}, consumerKey : {} }", @@ -138,19 +138,33 @@ public static void validateSubscriptionUsingConsumerKey(APIKeyValidationInfoDTO if (datastore != null) { // Get application key mapping using the consumer key, key type and security scheme - keyMapping = datastore.getMatchingApplicationKeyMapping(consumerKey, keyType, securityScheme); + keyMapping = datastore.getMatchingApplicationKeyMapping(consumerKey, keyType, securityScheme, + validationInfo.getEnvironment()); if (keyMapping != null) { // Get application and application mapping using application UUID String applicationUUID = keyMapping.getApplicationUUID(); app = datastore.getMatchingApplication(applicationUUID); - appMapping = datastore.getMatchingApplicationMapping(applicationUUID); + appMappings = datastore.getMatchingApplicationMappings(applicationUUID); - if (appMapping != null && app != null) { + if (appMappings != null && app != null) { // Get subscription using the subscription UUID - String subscriptionUUID = appMapping.getSubscriptionUUID(); - sub = datastore.getMatchingSubscription(subscriptionUUID); + for (ApplicationMapping appMapping : appMappings) { + String subscriptionUUID = appMapping.getSubscriptionUUID(); + Subscription subscription = datastore.getMatchingSubscription(subscriptionUUID); + if (validationInfo.getApiName().equals(subscription.getSubscribedApi().getName())) { + // Validate API version + String versionRegex = subscription.getSubscribedApi().getVersion(); + String versionToMatch = validationInfo.getApiVersion(); + Pattern pattern = Pattern.compile(versionRegex); + Matcher matcher = pattern.matcher(versionToMatch); + if (matcher.matches()) { + sub = subscription; + break; + } + } + } // Validate subscription if (sub != null) { validate(validationInfo, app, sub); @@ -258,23 +272,6 @@ private static void validate(APIKeyValidationInfoDTO infoDTO, Application app, S infoDTO.setAuthorized(false); return; } - - // Validate API details embedded within the subscription - // Validate API name - if (!infoDTO.getApiName().equals(sub.getSubscribedApi().getName())) { - infoDTO.setAuthorized(false); - return; - } - // Validate API version - String versionRegex = sub.getSubscribedApi().getVersion(); - String versionToMatch = infoDTO.getApiVersion(); - Pattern pattern = Pattern.compile(versionRegex); - Matcher matcher = pattern.matcher(versionToMatch); - if (!matcher.matches()) { - infoDTO.setAuthorized(false); - return; - } - infoDTO.setApplicationUUID(app.getUUID()); infoDTO.setSubscriber(app.getOwner()); infoDTO.setApplicationName(app.getName()); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java index 17f74bb93..510783ab3 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/jwt/JWTAuthenticator.java @@ -352,7 +352,9 @@ private void validateSubscriptionUsingConsumerKey(APIKeyValidationInfoDTO valida validationInfo.setApiVersion(version); validationInfo.setApiContext(context); validationInfo.setConsumerKey(consumerKey); - validationInfo.setType(envType); + validationInfo.setType(matchedAPI.getApiType()); + validationInfo.setEnvType(envType); + validationInfo.setEnvironment(matchedAPI.getEnvironment()); validationInfo.setSecurityScheme(APIConstants.API_SECURITY_OAUTH2); validationInfo.setSubscriberOrganization(organization); validationInfo.setApiContext(matchedAPI.getBasePath()); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationKeyMappingDTO.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationKeyMappingDTO.java index cd3d98aa7..439a3d979 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationKeyMappingDTO.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationKeyMappingDTO.java @@ -60,16 +60,16 @@ public void setEnvID(String envID) { private String keyType; private String envID; - public String getOrganization() { + public String getOrganizationId() { - return organization; + return organizationId; } - public void setOrganization(String organization) { + public void setOrganizationId(String organizationId) { - this.organization = organization; + this.organizationId = organizationId; } - private String organization; + private String organizationId; } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationMappingDto.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationMappingDto.java index d232d37af..3b2e7235f 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationMappingDto.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/ApplicationMappingDto.java @@ -37,15 +37,15 @@ public void setSubscriptionRef(String subscriptionRef) { private String applicationRef; private String subscriptionRef; - private String organization; + private String organizationId; - public String getOrganization() { + public String getOrganizationId() { - return organization; + return organizationId; } - public void setOrganization(String organization) { + public void setOrganizationId(String organizationId) { - this.organization = organization; + this.organizationId = organizationId; } } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/EventingGrpcClient.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/EventingGrpcClient.java index ec88b084a..2083cc141 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/EventingGrpcClient.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/EventingGrpcClient.java @@ -46,7 +46,6 @@ public class EventingGrpcClient implements Runnable { private static EventingGrpcClient instance; private ManagedChannel channel; private EventStreamServiceGrpc.EventStreamServiceStub stub; - private final SubscriptionDataStoreImpl subscriptionDataStore; private final String host; private final String hostname; private final int port; @@ -56,7 +55,6 @@ private EventingGrpcClient(String host, String hostname, int port) { this.host = host; this.hostname = hostname; this.port = port; - this.subscriptionDataStore = SubscriptionDataStoreImpl.getInstance(); initConnection(); } @@ -140,34 +138,35 @@ private void handleNotificationEvent(Event event) { break; case "APPLICATION_CREATED": Application application = event.getApplication(); - subscriptionDataStore.addApplication(application); + SubscriptionDataStoreUtil.addApplication(application); break; case "SUBSCRIPTION_CREATED": case "SUBSCRIPTION_UPDATED": - subscriptionDataStore.addSubscription(event.getSubscription()); + SubscriptionDataStoreUtil.addSubscription(event.getSubscription()); + break; case "APPLICATION_MAPPING_CREATED": case "APPLICATION_MAPPING_UPDATED": - subscriptionDataStore.addApplicationMapping(event.getApplicationMapping()); + SubscriptionDataStoreUtil.addApplicationMapping(event.getApplicationMapping()); break; case "APPLICATION_KEY_MAPPING_CREATED": case "APPLICATION_KEY_MAPPING_UPDATED": - subscriptionDataStore.addApplicationKeyMapping(event.getApplicationKeyMapping()); + SubscriptionDataStoreUtil.addApplicationKeyMapping(event.getApplicationKeyMapping()); break; case "APPLICATION_UPDATED": - subscriptionDataStore.addApplication(event.getApplication()); + SubscriptionDataStoreUtil.addApplication(event.getApplication()); break; case "APPLICATION_MAPPING_DELETED": - subscriptionDataStore.removeApplicationMapping(event.getApplicationMapping()); + SubscriptionDataStoreUtil.removeApplicationMapping(event.getApplicationMapping()); break; case "APPLICATION_KEY_MAPPING_DELETED": - subscriptionDataStore.removeApplicationKeyMapping(event.getApplicationKeyMapping()); + SubscriptionDataStoreUtil.removeApplicationKeyMapping(event.getApplicationKeyMapping()); break; case "SUBSCRIPTION_DELETED": - subscriptionDataStore.removeSubscription(event.getSubscription()); + SubscriptionDataStoreUtil.removeSubscription(event.getSubscription()); break; case "APPLICATION_DELETED": - subscriptionDataStore.removeApplication(event.getApplication()); + SubscriptionDataStoreUtil.removeApplication(event.getApplication()); break; default: logger.error("Unknown event type received from the server"); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStore.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStore.java index 4612de959..33be66ea2 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStore.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStore.java @@ -23,6 +23,7 @@ import org.wso2.apk.enforcer.security.jwt.validator.JWTValidator; import java.util.List; +import java.util.Set; /** * A Facade for obtaining Subscription related Data. @@ -60,7 +61,7 @@ void addApplicationKeyMappings( * @param uuid Application UUID * @return ApplicationMapping which match the given UUID */ - ApplicationMapping getMatchingApplicationMapping(String uuid); + Set getMatchingApplicationMappings(String uuid); /** * Filter the application key mapping map based on provided parameters @@ -68,10 +69,11 @@ void addApplicationKeyMappings( * @param applicationIdentifier Application identifier * @param keyType Key type, i.e. PRODUCTION or SANDBOX * @param securityScheme Security scheme + * @param envType * @return ApplicationKeyMapping which match the given parameters */ ApplicationKeyMapping getMatchingApplicationKeyMapping(String applicationIdentifier, String keyType, - String securityScheme); + String securityScheme, String envType); /** * Filter the applications map based on the provided parameters. diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java index 08d4e2f83..a326faaf3 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreImpl.java @@ -40,9 +40,11 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -78,8 +80,6 @@ public Application getApplicationById(String appUUID) { return applicationMap.get(appUUID); } - - @Override public Subscription getSubscriptionById(String appId, String apiId) { @@ -128,7 +128,6 @@ public void addApplications(List applicationList) { this.applicationMap = newApplicationMap; } - public void addApplicationKeyMappings(List applicationKeyMappingList) { Map newApplicationKeyMappingMap = new ConcurrentHashMap<>(); @@ -156,7 +155,7 @@ public void addApplicationMappings(List applicationMappin appMapping.setUuid(applicationMapping.getUuid()); appMapping.setApplicationUUID(applicationMapping.getApplicationRef()); appMapping.setSubscriptionUUID(applicationMapping.getSubscriptionRef()); - appMapping.setOrganization(applicationMapping.getOrganization()); + appMapping.setOrganization(applicationMapping.getOrganizationId()); newApplicationMappingMap.put(appMapping.getCacheKey(), appMapping); } if (log.isDebugEnabled()) { @@ -167,47 +166,25 @@ public void addApplicationMappings(List applicationMappin @Override public ApplicationKeyMapping getMatchingApplicationKeyMapping(String applicationIdentifier, String keyType, - String securityScheme) { - - for (ApplicationKeyMapping applicationKeyMapping : applicationKeyMappingMap.values()) { - boolean isApplicationIdentifierMatching = false; - boolean isSecuritySchemeMatching = false; - boolean isKeyTypeMatching = false; - - if (StringUtils.isNotEmpty(applicationIdentifier)) { - if (applicationKeyMapping.getApplicationIdentifier().equals(applicationIdentifier)) { - isApplicationIdentifierMatching = true; - } - } - if (StringUtils.isNotEmpty(securityScheme)) { - if (applicationKeyMapping.getSecurityScheme().equals(securityScheme)) { - isSecuritySchemeMatching = true; - } - } - if (StringUtils.isNotEmpty(keyType)) { - if (applicationKeyMapping.getKeyType().equals(keyType)) { - isKeyTypeMatching = true; - } - } + String securityScheme, String envType) { - if (isApplicationIdentifierMatching && isSecuritySchemeMatching && isKeyTypeMatching) { - return applicationKeyMapping; - } - } - return null; + String cacheKey = SubscriptionDataStoreUtil.getApplicationKeyMappingCacheKey(applicationIdentifier, keyType, + securityScheme, envType); + return applicationKeyMappingMap.get(cacheKey); } @Override - public ApplicationMapping getMatchingApplicationMapping(String uuid) { + public Set getMatchingApplicationMappings(String uuid) { - for (ApplicationMapping applicationMapping : applicationMappingMap.values()) { - if (StringUtils.isNotEmpty(uuid)) { + Set applicationMappings = new HashSet<>(); + if (StringUtils.isNotEmpty(uuid)) { + for (ApplicationMapping applicationMapping : applicationMappingMap.values()) { if (applicationMapping.getApplicationUUID().equals(uuid)) { - return applicationMapping; + applicationMappings.add(applicationMapping); } } } - return null; + return applicationMappings; } @Override diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreUtil.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreUtil.java index 6902c32fb..22a576d07 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreUtil.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStoreUtil.java @@ -22,8 +22,13 @@ import feign.gson.GsonDecoder; import feign.gson.GsonEncoder; import feign.slf4j.Slf4jLogger; +import org.wso2.apk.enforcer.common.CacheableEntity; import org.wso2.apk.enforcer.config.ConfigHolder; import org.wso2.apk.enforcer.discovery.JWTIssuerDiscoveryClient; +import org.wso2.apk.enforcer.discovery.subscription.Application; +import org.wso2.apk.enforcer.discovery.subscription.ApplicationKeyMapping; +import org.wso2.apk.enforcer.discovery.subscription.ApplicationMapping; +import org.wso2.apk.enforcer.discovery.subscription.Subscription; import org.wso2.apk.enforcer.util.ApacheFeignHttpClient; import org.wso2.apk.enforcer.util.FilterUtils; @@ -47,14 +52,8 @@ private SubscriptionDataStoreUtil() { String commonControllerHostname = ConfigHolder.getInstance().getEnvVarConfig().getCommonControllerHostname(); int commonControllerRestPort = Integer.parseInt(ConfigHolder.getInstance().getEnvVarConfig().getCommonControllerRestPort()); - subscriptionValidationDataRetrievalRestClient = Feign.builder() - .encoder(new GsonEncoder()) - .decoder(new GsonDecoder()) - .logger(new Slf4jLogger()) - .client(new ApacheFeignHttpClient(FilterUtils.getMutualSSLHttpClient("https", - Arrays.asList(commonControllerHost, commonControllerHostname)))) - .target(SubscriptionValidationDataRetrievalRestClient.class, - "https://" + commonControllerHost + ":" + commonControllerRestPort); + subscriptionValidationDataRetrievalRestClient = + Feign.builder().encoder(new GsonEncoder()).decoder(new GsonDecoder()).logger(new Slf4jLogger()).client(new ApacheFeignHttpClient(FilterUtils.getMutualSSLHttpClient("https", Arrays.asList(commonControllerHost, commonControllerHostname)))).target(SubscriptionValidationDataRetrievalRestClient.class, "https://" + commonControllerHost + ":" + commonControllerRestPort); } public static final String DELEM_PERIOD = "."; @@ -95,18 +94,13 @@ private static void loadApplicationKeyMappings() { List list = applicationKeyMappings.getList(); Map> orgWizeMAp = new HashMap<>(); for (ApplicationKeyMappingDTO applicationKeyMappingDTO : list) { - String organization = applicationKeyMappingDTO.getOrganization(); + String organization = applicationKeyMappingDTO.getOrganizationId(); List applicationKeyMappingDTOS = orgWizeMAp.computeIfAbsent(organization, k -> new ArrayList<>()); applicationKeyMappingDTOS.add(applicationKeyMappingDTO); } orgWizeMAp.forEach((k, v) -> { - SubscriptionDataStore subscriptionDataStore = SubscriptionDataHolder.getInstance() - .getSubscriptionDataStore(k); - if (subscriptionDataStore == null) { - subscriptionDataStore = SubscriptionDataHolder.getInstance() - .initializeSubscriptionDataStore(k); - } + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(k); subscriptionDataStore.addApplicationKeyMappings(v); }); }).start(); @@ -116,23 +110,18 @@ private static void loadApplicationKeyMappings() { private static void loadApplicationMappings() { new Thread(() -> { - ApplicationMappingDtoList applicationMappings = subscriptionValidationDataRetrievalRestClient - .getAllApplicationMappings(); + ApplicationMappingDtoList applicationMappings = + subscriptionValidationDataRetrievalRestClient.getAllApplicationMappings(); List list = applicationMappings.getList(); Map> orgWizeMAp = new HashMap<>(); for (ApplicationMappingDto applicationMappingDto : list) { - String organization = applicationMappingDto.getOrganization(); + String organization = applicationMappingDto.getOrganizationId(); List applicationMappingDtos = orgWizeMAp.computeIfAbsent(organization, k -> new ArrayList<>()); applicationMappingDtos.add(applicationMappingDto); } orgWizeMAp.forEach((k, v) -> { - SubscriptionDataStore subscriptionDataStore = SubscriptionDataHolder.getInstance() - .getSubscriptionDataStore(k); - if (subscriptionDataStore == null) { - subscriptionDataStore = SubscriptionDataHolder.getInstance() - .initializeSubscriptionDataStore(k); - } + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(k); subscriptionDataStore.addApplicationMappings(v); }); }).start(); @@ -153,17 +142,11 @@ private static void loadApplications() { Map> orgWizeMAp = new HashMap<>(); for (ApplicationDto applicationDto : list) { String organization = applicationDto.getOrganizationId(); - List applicationDtos = orgWizeMAp.computeIfAbsent(organization, - k -> new ArrayList<>()); + List applicationDtos = orgWizeMAp.computeIfAbsent(organization, k -> new ArrayList<>()); applicationDtos.add(applicationDto); } orgWizeMAp.forEach((k, v) -> { - SubscriptionDataStore subscriptionDataStore = SubscriptionDataHolder.getInstance() - .getSubscriptionDataStore(k); - if (subscriptionDataStore == null) { - subscriptionDataStore = SubscriptionDataHolder.getInstance() - .initializeSubscriptionDataStore(k); - } + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(k); subscriptionDataStore.addApplications(v); }); }).start(); @@ -182,18 +165,95 @@ private static void loadSubscriptions() { subscriptionDtos.add(subscriptionDto); } orgWizeMAp.forEach((k, v) -> { - SubscriptionDataStore subscriptionDataStore = SubscriptionDataHolder.getInstance() - .getSubscriptionDataStore(k); - if (subscriptionDataStore == null) { - subscriptionDataStore = SubscriptionDataHolder.getInstance() - .initializeSubscriptionDataStore(k); - } + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(k); subscriptionDataStore.addSubscriptions(v); }); }).start(); } - public void loadStartupArtifacts(){ + public static String getApplicationKeyMappingCacheKey(String applicationIdentifier, String keyType, + String securityScheme, String envType) { + + return securityScheme + CacheableEntity.DELEM_PERIOD + envType + CacheableEntity.DELEM_PERIOD + keyType + CacheableEntity.DELEM_PERIOD + applicationIdentifier; + } + + public static void addApplication(Application application) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(application.getOrganization()); + subscriptionDataStore.addApplication(application); + + } + + public static void addSubscription(Subscription subscription) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(subscription.getOrganization()); + subscriptionDataStore.addSubscription(subscription); + + } + + public static void addApplicationMapping(ApplicationMapping applicationMapping) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(applicationMapping.getOrganization()); + subscriptionDataStore.addApplicationMapping(applicationMapping); + + } + + public static void addApplicationKeyMapping(ApplicationKeyMapping applicationKeyMapping) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(applicationKeyMapping.getOrganization()); + subscriptionDataStore.addApplicationKeyMapping(applicationKeyMapping); + + } + + public static void removeApplicationMapping(ApplicationMapping applicationMapping) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(applicationMapping.getOrganization()); + subscriptionDataStore.removeApplicationMapping(applicationMapping); + + } + + private static SubscriptionDataStore getSubscriptionDataStore(String organization) { + + SubscriptionDataStore subscriptionDataStore = + SubscriptionDataHolder.getInstance().getSubscriptionDataStore(organization); + if (subscriptionDataStore == null) { + synchronized (organization.concat("subscriptionDataStore").intern()) { + subscriptionDataStore = SubscriptionDataHolder.getInstance().getSubscriptionDataStore(organization); + if (subscriptionDataStore != null) { + return subscriptionDataStore; + } + subscriptionDataStore = SubscriptionDataHolder.getInstance().initializeSubscriptionDataStore(organization); + return subscriptionDataStore; + } + } + return subscriptionDataStore; + } + + public static void removeApplicationKeyMapping(ApplicationKeyMapping applicationKeyMapping) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(applicationKeyMapping.getOrganization()); + + subscriptionDataStore.removeApplicationKeyMapping(applicationKeyMapping); + + } + + public static void removeSubscription(Subscription subscription) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(subscription.getOrganization()); + + subscriptionDataStore.removeSubscription(subscription); + + } + + public static void removeApplication(Application application) { + + SubscriptionDataStore subscriptionDataStore = getSubscriptionDataStore(application.getOrganization()); + subscriptionDataStore.removeApplication(application); + + } + + public void loadStartupArtifacts() { + loadApplications(); loadSubscriptions(); loadApplicationMappings(); diff --git a/helm-charts/templates/data-plane/gateway-components/common-log-conf.yaml b/helm-charts/templates/data-plane/gateway-components/common-log-conf.yaml index a066b5059..3d85d7ef1 100644 --- a/helm-charts/templates/data-plane/gateway-components/common-log-conf.yaml +++ b/helm-charts/templates/data-plane/gateway-components/common-log-conf.yaml @@ -52,4 +52,45 @@ data: [commoncontroller.webServer] port = 9543 + log_config.toml: | + # The logging configuration for Adapter + + ## Adapter root Level configurations + + logfile = "adapter.log" # This file will be created inside adapter container. + logLevel = "INFO" # LogLevels can be "DEBG", "FATL", "ERRO", "WARN", "INFO", "PANC" + LogFormat = "TEXT" # Values can be "JSON", "TEXT" + + [rotation] + MaxSize = 10 # In MegaBytes (MB) + MaxBackups = 3 + MaxAge = 2 # In days + Compress = true + + ## Adapter package Level configurations + + [[pkg]] + name = "github.com/wso2/apk/common-adapter/internal/operator" + logLevel = "INFO" # LogLevels can be "DEBG", "FATL", "ERRO", "WARN", "INFO", "PANC" + [[pkg]] + name = "github.com/wso2/apk/common-controller/internal/utils" + logLevel = "DEBG" # LogLevels can be "DEBG", "FATL", "ERRO", "WARN", "INFO", "PANC" + [[pkg]] + + # The logging configuration for Router + + [accessLogs] + enable = false + logfile = "/tmp/envoy.access.log" # This file will be created inside router container. + format = "[%START_TIME%] '%REQ(:METHOD)% %DYNAMIC_METADATA(envoy.filters.http.ext_authz:originalPath)% %REQ(:PATH)% %PROTOCOL%' %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% '%REQ(X-FORWARDED-FOR)%' '%REQ(USER-AGENT)%' '%REQ(X-REQUEST-ID)%' '%REQ(:AUTHORITY)%' '%UPSTREAM_HOST%'\n" + + [wireLogs] + enable = false + include = ["Headers", "Body", "Trailers"] + + # [[pkg]] + # name = "github.com/wso2/apk/Adapter/pkg/xds" + # logLevel = "INFO" + + {{- end -}} diff --git a/test/cucumber-tests/CRs/artifacts.yaml b/test/cucumber-tests/CRs/artifacts.yaml index c947f850d..3f102e158 100644 --- a/test/cucumber-tests/CRs/artifacts.yaml +++ b/test/cucumber-tests/CRs/artifacts.yaml @@ -646,3 +646,88 @@ spec: - name: endpoint3 protocol: TCP port: 9000 +--- +kind: Application +apiVersion: cp.wso2.com/v1alpha2 +metadata: + name: 583e4146-7ef5-11ee-b962-0242ac120003 + namespace : apk-integration-test +spec: + name: sample-app + owner: admin + organization: default + securitySchemes: + oauth2: + environments: + - envId: Default + appId: 45f1c5c8-a92e-11ed-afa1-0242ac120005 + keyType: PRODUCTION +--- +kind: Application +apiVersion: cp.wso2.com/v1alpha2 +metadata: + name: 583e4146-7ef5-11ee-b962-0242ac120004 + namespace : apk-integration-test +spec: + name: sample-app1 + owner: admin + organization: default + securitySchemes: + oauth2: + environments: + - envId: Default + appId: 45f1c5c8-a92e-11ed-afa1-0242ac120006 + keyType: PRODUCTION + - envId: Default + appId: 45f1c5c8-a92e-11ed-afa1-0242ac120007 + keyType: SANDBOX +--- +kind: Application +apiVersion: cp.wso2.com/v1alpha2 +metadata: + name: 583e4146-7ef5-11ee-b962-0242ac120005 + namespace : apk-integration-test +spec: + name: sample-app1 + owner: admin + organization: default + securitySchemes: + oauth2: + environments: + - envId: Default + appId: 45f1c5c8-a92e-11ed-afa1-0242ac120008 + keyType: PRODUCTION + - envId: Default + appId: 45f1c5c8-a92e-11ed-afa1-0242ac120009 + keyType: SANDBOX +--- +apiVersion: cp.wso2.com/v1alpha2 +kind: Subscription +metadata: + name: 583e4146-7ef6-11ee-b962-0242ac120003 + namespace: apk-integration-test +spec: + organization: "default" + subscriptionStatus: "ACTIVE" + api: + name: "subscription-api" + version: "1.0.0" + +--- +apiVersion: cp.wso2.com/v1alpha2 +kind: ApplicationMapping +metadata: + name: 583e4146-7ef5-11ee-b964-0242ac120002 + namespace: apk-integration-test +spec: + applicationRef: 583e4146-7ef5-11ee-b962-0242ac120003 + subscriptionRef: 583e4146-7ef6-11ee-b962-0242ac120003 +--- +apiVersion: cp.wso2.com/v1alpha2 +kind: ApplicationMapping +metadata: + name: 583e4146-7ef5-11ee-b964-0242ac120004 + namespace: apk-integration-test +spec: + applicationRef: 583e4146-7ef5-11ee-b962-0242ac120004 + subscriptionRef: 583e4146-7ef6-11ee-b962-0242ac120003 \ No newline at end of file diff --git a/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/JWTGeneratorSteps.java b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/JWTGeneratorSteps.java index dffad6511..9b3d94028 100644 --- a/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/JWTGeneratorSteps.java +++ b/test/cucumber-tests/src/test/java/org/wso2/apk/integration/api/JWTGeneratorSteps.java @@ -58,6 +58,30 @@ public void generateTokenFromIdp1(String kid) throws IOException, CertificateExc String jwtToken = signedJWT.serialize(); sharedContext.addStoreValue("idp-1-token", jwtToken); } + @Then("I generate JWT token from idp1 with kid {string} and consumer_key {string}") + public void generateTokenFromIdp1WithConsumerKey(String kid,String consumerKey) throws IOException, CertificateException, KeyStoreException, + NoSuchAlgorithmException, JOSEException { + + URL url = Resources.getResource("artifacts/jwtcert/idp1.jks"); + File keyStoreFile = new File(url.getPath()); + KeyStore keyStore = KeyStore.getInstance(keyStoreFile, "wso2carbon".toCharArray()); + RSAKey rsaKey = RSAKey.load(keyStore, "idp1Key", "wso2carbon".toCharArray()); + JWSSigner signer = new RSASSASigner(rsaKey); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() + .subject("alice") + .issuer("https://idp1.com") + .expirationTime(new Date(new Date().getTime() + 60 * 1000)) + .jwtID(UUID.randomUUID().toString()) + .claim("azp", consumerKey) + .claim("scope", Constants.API_CREATE_SCOPE) + .build(); + SignedJWT signedJWT = new SignedJWT( + new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(kid).build(), + claimsSet); + signedJWT.sign(signer); + String jwtToken = signedJWT.serialize(); + sharedContext.addStoreValue("idp-1-"+consumerKey+"-token", jwtToken); + } @And("I have a valid token for organization {string}") diff --git a/test/cucumber-tests/src/test/resources/artifacts/apk-confs/subscription-api.yaml b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/subscription-api.yaml new file mode 100644 index 000000000..aed8e846d --- /dev/null +++ b/test/cucumber-tests/src/test/resources/artifacts/apk-confs/subscription-api.yaml @@ -0,0 +1,27 @@ +--- +id: "subscription-api" +name: "subscription-api" +basePath: "/subscription-api" +version: "1.0.0" +type: "REST" +defaultVersion: true +subscriptionValidation: true +endpointConfigurations: + production: + endpoint: "http://backend:80/anything/prod" + sandbox: + endpoint: "http://backend:80/anything/sand" +operations: + - target: "/endpoint1" + verb: "GET" + secured: true + scopes: [] + endpointConfigurations: + production: + endpoint: "http://backend:80/anything/prodr" + sandbox: + endpoint: "http://backend:80/anything/sandr" + - target: "/endpoint2" + verb: "GET" + secured: true + scopes: [] diff --git a/test/cucumber-tests/src/test/resources/tests/api/APISubscription.feature b/test/cucumber-tests/src/test/resources/tests/api/APISubscription.feature new file mode 100644 index 000000000..36304a6ab --- /dev/null +++ b/test/cucumber-tests/src/test/resources/tests/api/APISubscription.feature @@ -0,0 +1,72 @@ +Feature: API Subscription Feature + Scenario: testing api subscriptions. + Given The system is ready + And I have a valid subscription + When I use the APK Conf file "artifacts/apk-confs/subscription-api.yaml" + 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/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 403 response code, not accepting + |429| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + Then the response status code should be 403 + Then I generate JWT token from idp1 with kid "123-456" and consumer_key "45f1c5c8-a92e-11ed-afa1-0242ac120005" + Then I set headers + |Authorization|bearer ${idp-1-45f1c5c8-a92e-11ed-afa1-0242ac120005-token}| + And I send "GET" request to "https://default.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 200 response code, not accepting + |429| + |401| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + Then the response status code should be 403 + + Then I generate JWT token from idp1 with kid "123-456" and consumer_key "45f1c5c8-a92e-11ed-afa1-0242ac120006" + Then I set headers + |Authorization|bearer ${idp-1-45f1c5c8-a92e-11ed-afa1-0242ac120006-token}| + And I send "GET" request to "https://default.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 200 response code, not accepting + |429| + |401| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 403 response code, not accepting + |200| + |429| + Then I generate JWT token from idp1 with kid "123-456" and consumer_key "45f1c5c8-a92e-11ed-afa1-0242ac120007" + Then I set headers + |Authorization|bearer ${idp-1-45f1c5c8-a92e-11ed-afa1-0242ac120007-token}| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + Then the response status code should be 200 + And I send "GET" request to "https://default.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 403 response code, not accepting + |200| + |429| + Then I generate JWT token from idp1 with kid "123-456" and consumer_key "45f1c5c8-a92e-11ed-afa1-0242ac120008" + Then I set headers + |Authorization|bearer ${idp-1-45f1c5c8-a92e-11ed-afa1-0242ac120008-token}| + And I send "GET" request to "https://default.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 403 response code, not accepting + |200| + |401| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + And I eventually receive 403 response code, not accepting + |200| + |429| + Then I generate JWT token from idp1 with kid "123-456" and consumer_key "45f1c5c8-a92e-11ed-afa1-0242ac120009" + Then I set headers + |Authorization|bearer ${idp-1-45f1c5c8-a92e-11ed-afa1-0242ac120009-token}| + And I send "GET" request to "https://default.sandbox.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + Then the response status code should be 403 + And I send "GET" request to "https://default.gw.wso2.com:9095/subscription-api/1.0.0/endpoint1" with body "" + Then the response status code should be 403 + Scenario Outline: Undeploy API + Given The system is ready + And I have a valid subscription + When I undeploy the API whose ID is "" + Then the response status code should be + + Examples: + | apiID | expectedStatusCode | + | subscription-api | 202 | From 3607e88173bdcd237f36087154aa29a3b005cb8b Mon Sep 17 00:00:00 2001 From: tharindu1st Date: Thu, 14 Dec 2023 11:33:06 +0530 Subject: [PATCH 2/2] fix test --- .../apk/enforcer/jwt/JWTValidatorTest.java | 64 +++++++++++-------- .../gateway-runtime-deployment.yaml | 22 ------- 2 files changed, 36 insertions(+), 50 deletions(-) diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/test/java/org/wso2/apk/enforcer/jwt/JWTValidatorTest.java b/gateway/enforcer/org.wso2.apk.enforcer/src/test/java/org/wso2/apk/enforcer/jwt/JWTValidatorTest.java index a527b06c0..3e4b44b90 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/test/java/org/wso2/apk/enforcer/jwt/JWTValidatorTest.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/test/java/org/wso2/apk/enforcer/jwt/JWTValidatorTest.java @@ -17,13 +17,6 @@ package org.wso2.apk.enforcer.jwt; import com.google.common.cache.LoadingCache; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.logging.log4j.LogManager; @@ -31,7 +24,6 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.wso2.apk.enforcer.common.CacheProvider; @@ -61,6 +53,12 @@ import org.wso2.apk.enforcer.subscription.SubscriptionDataHolder; import org.wso2.apk.enforcer.subscription.SubscriptionDataStore; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + public class JWTValidatorTest { @Before @@ -579,7 +577,7 @@ public void testNoCacheExpiredJWTValidator() throws EnforcerException { @Test public void testTamperedPayloadJWTValidator() throws EnforcerException { - String organization = "org1"; + String organization = "org2"; String environment = "development"; String issuer = "https://localhost:9443/oauth2/token"; String signature = "sBgeoqJn0log5EZflj_G7ADvm6B3KQ9bdfFCEFVQS1U3oY9" + @@ -589,28 +587,30 @@ public void testTamperedPayloadJWTValidator() throws EnforcerException { "EuSe9w"; String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5UZG1aak00WkRrM05qWTBZemM1T" + "W1abU9EZ3dNVEUzTVdZd05ERTVNV1JsWkRnNE56YzRaQT09In0" + - ".eyJhdWQiOiJodHRwOlwvXC9vcmcud3NvMi5hcGltZ3RcL2dhdGV" + - "3YXkiLCJzdWIiOiJhZG1pbkBjYXJib24uc3VwZXIiLCJhcHBsaWNhdGlvbiI6eyJvd25lciI6ImFkbWluIiwidGllclF1b3RhVHlwZ" + - "SI6InJlcXVlc3RDb3VudCIsInRpZXIiOiJVbmxpbWl0ZWQiLCJuYW1lIjoiRGVmYXVsdEFwcGxpY2F0aW9uIiwiaWQiOjEsInV1aWQ" + - "iOm51bGx9LCJzY29wZSI6ImFtX2FwcGxpY2F0aW9uX3Njb3BlIGRlZmF1bHQiLCJpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0" + - "NDNcL29hdXRoMlwvdG9rZW4iLCJ0aWVySW5mbyI6e30sImtleXR5cGUiOiJQUk9EVUNUSU9OIiwic3Vic2NyaWJlZEFQSXMiOltdL" + - "CJjb25zdW1lcktleSI6IlhnTzM5NklIRks3ZUZZeWRycVFlNEhLR3oxa2EiLCJleHAiOjE1OTAzNDIzMTMsImlhdCI6MTU5MDMzO" + - "DcxMywianRpIjoiYjg5Mzg3NjgtMjNmZC00ZGVjLThiNzAtYmVkNDVlYjdjMzNkIn0." + signature; + ".ewogICJhdWQiOiAiaHR0cDovL29yZy53c28yLmFwaW1ndC9nYXRld2F5IiwKICAic3ViIjogImFkbWluQGNhcmJ" + + "vbi5zdXBlciIsCiAgImFwcGxpY2F0aW9uIjogewogICAgIm93bmVyIjogImFkbWluIiwKICAgICJ0aWVyUXVvdGFU" + + "eXBlIjogInJlcXVlc3RDb3VudCIsCiAgICAidGllciI6ICJVbmxpbWl0ZWQiLAogICAgIm5hbWUiOiAiRGVmYXVsd" + + "EFwcGxpY2F0aW9uIiwKICAgICJpZCI6IDEsCiAgICAidXVpZCI6IG51bGwKICB9LAogICJzY29wZSI6ICJhbV9hcHB" + + "saWNhdGlvbl9zY29wZSBkZWZhdWx0IiwKICAiaXNzIjogImh0dHBzOi8vbG9jYWxob3N0Ojk0NDMvb2F1dGgyL3Rva" + + "2VuIiwKICAidGllckluZm8iOiB7fSwKICAia2V5dHlwZSI6ICJQUk9EVUNUSU9OIiwKICAic3Vic2NyaWJlZEFQSXM" + + "iOiBbXSwKICAiY29uc3VtZXJLZXkiOiAiWGdPMzk2SUhGSzdlRll5ZHJxUWU0SEtHejFrYSIsCiAgImV4cCI6IDQxMz" + + "IzODM0NzcsCiAgImlhdCI6IDE1OTAzMzg3MTMsCiAgImp0aSI6ICJiODkzODc2OC0yM2ZkLTRkZWMtOGI3MC1iZWQ0N" + + "WViN2MzM2QiCn0=." + signature; String tamperedJWT = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5UZG1aak00WkRrM05qWTBZemM1T" + "W1abU9EZ3dNVEUzTVdZd05ERTVNV1JsWkRnNE56YzRaQT09In0" + - ".ewogICJhdWQiOiAiaHR0cDovL29yZy53c28yLmFwaW1ndC9nYXRld2F5IiwKICAic3ViIjogImFkbWluQGNhcm" + - "Jvbi5zdXBlciIsCiAgImFwcGxpY2F0aW9uIjogewogICAgIm93bmVyIjogImFkbWluIiwKICAgICJ0aWVyUXVvd" + - "GFUeXBlIjogInJlcXVlc3RDb3VudCIsCiAgICAidGllciI6ICJVbmxpbWl0ZWQiLAogICAgIm5hbWUiOiAiRGVm" + - "YXVsdEFwcGxpY2F0aW9uMiIsCiAgICAiaWQiOiAyLAogICAgInV1aWQiOiBudWxsCiAgfSwKICAic2NvcGUiOiA" + - "iYW1fYXBwbGljYXRpb25fc2NvcGUgZGVmYXVsdCIsCiAgImlzcyI6ICJodHRwczovL2xvY2FsaG9zdDo5NDQzL2" + - "9hdXRoMi90b2tlbiIsCiAgInRpZXJJbmZvIjoge30sCiAgImtleXR5cGUiOiAiUFJPRFVDVElPTiIsCiAgInN1Y" + - "nNjcmliZWRBUElzIjogW10sCiAgImNvbnN1bWVyS2V5IjogIlhnTzM5NklIRks3ZUZZeWRycVFlNEhLR3oxa2Ei" + - "LAogICJleHAiOiAxNTkwMzQyMzEzLAogICJpYXQiOiAxNTkwMzM4NzEzLAogICJqdGkiOiAiYjg5Mzg3NjgtMjN" + - "mZC00ZGVjLThiNzAtYmVkNDVlYjdjMzNkIgp9." + signature; + ".ewogICJhdWQiOiAiaHR0cDovL29yZy53c28yLmFwaW1ndC9nYXRld2F5IiwKICAic3ViIjogImFkbWluQGNhcmJvbi5" + + "zdXBlciIsCiAgImFwcGxpY2F0aW9uIjogewogICAgIm93bmVyIjogImFkbWluIiwKICAgICJ0aWVyUXVvdGFUeXBlIjo" + + "gInJlcXVlc3RDb3VudCIsCiAgICAidGllciI6ICJVbmxpbWl0ZWQiLAogICAgIm5hbWUiOiAiRGVmYXVsdEFwcGxpY2F" + + "0aW9uMiIsCiAgICAiaWQiOiAyLAogICAgInV1aWQiOiBudWxsCiAgfSwKICAic2NvcGUiOiAiYW1fYXBwbGljYXRpb25" + + "fc2NvcGUgZGVmYXVsdCIsCiAgImlzcyI6ICJodHRwczovL2xvY2FsaG9zdDo5NDQzL29hdXRoMi90b2tlbiIsCiAgInR" + + "pZXJJbmZvIjoge30sCiAgImtleXR5cGUiOiAiUFJPRFVDVElPTiIsCiAgInN1YnNjcmliZWRBUElzIjogW10sCiAgImN" + + "vbnN1bWVyS2V5IjogIlhnTzM5NklIRks3ZUZZeWRycVFlNEhLR3oxa2EiLAogICJleHAiOiA0MTMyMzgzNDc3LAogICJ" + + "pYXQiOiAxNTkwMzM4NzEzLAogICJqdGkiOiAiYjg5Mzg3NjgtMjNmZC00ZGVjLThiNzAtYmVkNDVlYjdjMzNkIgp9." + + signature; JWTValidationInfo jwtValidationInfo = new JWTValidationInfo(); jwtValidationInfo.setValid(false); - jwtValidationInfo.setExpiryTime(System.currentTimeMillis() - 100); + jwtValidationInfo.setExpiryTime(System.currentTimeMillis() + 120000); jwtValidationInfo.setConsumerKey(UUID.randomUUID().toString()); jwtValidationInfo.setUser("user1"); jwtValidationInfo.setKeyManager("Default"); @@ -641,9 +641,17 @@ public void testTamperedPayloadJWTValidator() throws EnforcerException { Mockito.when(apiConfig.getOrganizationId()).thenReturn(organization); Mockito.when(requestContext.getMatchedAPI()).thenReturn(apiConfig); try (MockedStatic cacheProviderUtilDummy = Mockito.mockStatic(CacheProviderUtil.class); - MockedStatic keyValidatorDummy = Mockito.mockStatic(KeyValidator.class) + MockedStatic keyValidatorDummy = Mockito.mockStatic(KeyValidator.class); + MockedStatic subscriptionDataHolderMockedStatic = + Mockito.mockStatic(SubscriptionDataHolder.class); ) { CacheProvider cacheProvider = Mockito.mock(CacheProvider.class); + SubscriptionDataStore subscriptionDataStore = Mockito.mock(SubscriptionDataStore.class); + SubscriptionDataHolder subscriptionDataHolder = Mockito.mock(SubscriptionDataHolder.class); + subscriptionDataHolderMockedStatic.when(SubscriptionDataHolder::getInstance).thenReturn(subscriptionDataHolder); + Mockito.when(subscriptionDataHolder.getSubscriptionDataStore(organization)).thenReturn(subscriptionDataStore); + cacheProviderUtilDummy.when(() -> CacheProviderUtil.getOrganizationCache(organization)). + thenReturn(cacheProvider); LoadingCache gatewayKeyCache = Mockito.mock(LoadingCache.class); LoadingCache invalidTokenCache = Mockito.mock(LoadingCache.class); Mockito.when(gatewayKeyCache.getIfPresent(signature)).thenReturn(jwtValidationInfo); @@ -652,8 +660,8 @@ public void testTamperedPayloadJWTValidator() throws EnforcerException { Mockito.when(cacheProvider.getInvalidTokenCache()).thenReturn(invalidTokenCache); cacheProviderUtilDummy.when(() -> CacheProviderUtil.getOrganizationCache(organization)) .thenReturn(cacheProvider); - JWTValidator jwtValidator = Mockito.mock(JWTValidator.class); + Mockito.when(subscriptionDataStore.getJWTValidatorByIssuer(issuer, environment)).thenReturn(jwtValidator); Mockito.when(jwtValidator.validateToken(Mockito.eq(jwt), Mockito.any())).thenReturn(jwtValidationInfo); keyValidatorDummy.when(() -> KeyValidator.validateScopes(Mockito.any())).thenReturn(true); try { diff --git a/helm-charts/templates/data-plane/gateway-components/gateway-runtime/gateway-runtime-deployment.yaml b/helm-charts/templates/data-plane/gateway-components/gateway-runtime/gateway-runtime-deployment.yaml index 0426ebc38..98d3dc5f0 100644 --- a/helm-charts/templates/data-plane/gateway-components/gateway-runtime/gateway-runtime-deployment.yaml +++ b/helm-charts/templates/data-plane/gateway-components/gateway-runtime/gateway-runtime-deployment.yaml @@ -35,28 +35,6 @@ spec: checksum/config: {{ include (print $.Template.BasePath "/data-plane/gateway-components/log-conf.yaml") . | sha256sum }} spec: automountServiceAccountToken: false - initContainers: - - name: check-adapter - image: busybox:1.32 - env: - - name: ADAPTER_HOST - value: {{ template "apk-helm.resource.prefix" . }}-adapter-service.{{ .Release.Namespace }}.svc - - name: ADAPTER_XDS_PORT - value : "18000" - command: ['sh', '-c', 'echo -e "Checking for the availability of Adapter deployment"; while ! nc -z $ADAPTER_HOST $ADAPTER_XDS_PORT; do sleep 1; printf "-"; done; echo -e " >> Adapter has started";'] - - name: check-common-controller - image: busybox:1.32 - env: - - name: COMMON_CONTROLLER_HOST_NAME - value: {{ template "apk-helm.resource.prefix" . }}-common-controller-service.{{ .Release.Namespace }}.svc - - name: COMMON_CONTROLLER_XDS_PORT - value: "18002" - command: ['sh', '-c', 'echo -e "Checking for the availability of common-controller deployment"; while ! nc -z $COMMON_CONTROLLER_HOST_NAME $COMMON_CONTROLLER_XDS_PORT; do sleep 1; printf "-"; done; echo -e " >> common-controller has started";'] - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - readOnlyRootFilesystem: true containers: - name: enforcer image: {{ .Values.wso2.apk.dp.gatewayRuntime.deployment.enforcer.image }}