From f3aeb0bee21e2a299e9fe8ac33d721917f532cf9 Mon Sep 17 00:00:00 2001 From: tharindu1st Date: Tue, 12 Dec 2023 12:59:21 +0530 Subject: [PATCH] refactor-2 subscription --- .../enforcer/dto/APIKeyValidationInfoDTO.java | 11 +++++ .../models/ApplicationKeyMapping.java | 16 ++++++- .../apk/enforcer/security/KeyValidator.java | 45 +++++++++--------- .../security/jwt/JWTAuthenticator.java | 3 +- .../subscription/SubscriptionDataStore.java | 6 ++- .../SubscriptionDataStoreImpl.java | 47 +++++-------------- .../SubscriptionDataStoreUtil.java | 6 +++ 7 files changed, 71 insertions(+), 63 deletions(-) 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 8f43428090..c13c45f59d 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,7 @@ public class APIKeyValidationInfoDTO implements Serializable { private String apiContext; private String applicationUUID; private Map appAttributes; + private String envType; public String getOrganization() { @@ -431,5 +432,15 @@ public void setApiUUID(String apiUUID) { this.apiUUID = apiUUID; } + + public void setEnvType(String envType) { + + this.envType = envType; + } + + public String getEnvType() { + + return envType; + } } 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 aadc9f92e3..e9777c5377 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 6ff936dfcc..acadc8ce70 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,9 +119,9 @@ 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(); @@ -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.getEnvType()); 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 17f74bb930..576e080624 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,8 @@ 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.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/SubscriptionDataStore.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/subscription/SubscriptionDataStore.java index 4612de9597..33be66ea26 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 08d4e2f83f..f56b4a39ec 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<>(); @@ -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 6902c32fb1..e2cc70d9f9 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,6 +22,7 @@ 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.util.ApacheFeignHttpClient; @@ -193,6 +194,11 @@ private static void loadSubscriptions() { }).start(); } + 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 void loadStartupArtifacts(){ loadApplications(); loadSubscriptions();