From 964914cc6724d0c40f13c03f16c87936eac71587 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Fri, 5 Jan 2024 10:39:44 +0530 Subject: [PATCH 01/11] Supporting whitelisted organizations to access any environment with Production tokens. --- .../enforcer/security/jwt/JWTAuthenticator.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index fefc3392a6..95692fec2e 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -304,9 +304,6 @@ public AuthenticationContext authenticate(RequestContext requestContext) throws if (claims.getClaim("keytype") != null) { authenticationContext.setKeyType(claims.getClaim("keytype").toString()); } - // Check if the token has access to the gateway configured environment. - checkTokenEnvAgainstDeploymentType(requestContext.getAuthenticationContext().getKeyType(), - requestContext.getMatchedAPI()); if (!"Unlimited".equals(authenticationContext.getTier())) { // For subscription rate limiting, it is required to populate dynamic metadata String subscriptionId = authenticationContext.getApiUUID() + ":" + @@ -411,6 +408,19 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { + if (System.getenv("WHITELISTED_ORGANIZATIONS") != null) { + String[] whitelistedOrganizationsArray = + System.getenv("WHITELISTED_ORGANIZATIONS").split("\\s+"); + for (String whitelistedOrgId : whitelistedOrganizationsArray) { + if (matchedAPI.getOrganizationId().equalsIgnoreCase(whitelistedOrgId)) { + return; + } + } + throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), + APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, + APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT_ERROR_MESSAGE); + } + log.info("Deprecated: Production access token is used to access sandbox API deployment in " + "organization : " + matchedAPI.getOrganizationId()); return; From 4454bd949d4b7f5a10673b2e92fb55ab84f93518 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Fri, 5 Jan 2024 11:37:20 +0530 Subject: [PATCH 02/11] Adding static block --- .../connect/enforcer/security/jwt/JWTAuthenticator.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 95692fec2e..ee4257143f 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -79,6 +79,12 @@ public class JWTAuthenticator implements Authenticator { private final JWTValidator jwtValidator = new JWTValidator(); private final boolean isGatewayTokenCacheEnabled; private AbstractAPIMgtGatewayJWTGenerator jwtGenerator; + private static String[] whitelistedOrganizationsArray; + + static { + whitelistedOrganizationsArray = + System.getenv("WHITELISTED_ORGANIZATIONS").split("\\s+"); + } public JWTAuthenticator() { EnforcerConfig enforcerConfig = ConfigHolder.getInstance().getConfig(); @@ -409,8 +415,6 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { if (System.getenv("WHITELISTED_ORGANIZATIONS") != null) { - String[] whitelistedOrganizationsArray = - System.getenv("WHITELISTED_ORGANIZATIONS").split("\\s+"); for (String whitelistedOrgId : whitelistedOrganizationsArray) { if (matchedAPI.getOrganizationId().equalsIgnoreCase(whitelistedOrgId)) { return; From 9d9de220d322fcfbb50deb3c7974a07fa0243a55 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 10:03:19 +0530 Subject: [PATCH 03/11] Minor refactoring --- .../enforcer/security/jwt/JWTAuthenticator.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index ee4257143f..d2b5aa3c26 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -79,11 +79,15 @@ public class JWTAuthenticator implements Authenticator { private final JWTValidator jwtValidator = new JWTValidator(); private final boolean isGatewayTokenCacheEnabled; private AbstractAPIMgtGatewayJWTGenerator jwtGenerator; - private static String[] whitelistedOrganizationsArray; + private static final String[] prodTokenNonProdAllowedOrgs; static { - whitelistedOrganizationsArray = - System.getenv("WHITELISTED_ORGANIZATIONS").split("\\s+"); + if (System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS") != null) { + prodTokenNonProdAllowedOrgs = + System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS").split("\\s+"); + } else { + prodTokenNonProdAllowedOrgs = null; + } } public JWTAuthenticator() { @@ -414,8 +418,8 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { - if (System.getenv("WHITELISTED_ORGANIZATIONS") != null) { - for (String whitelistedOrgId : whitelistedOrganizationsArray) { + if (prodTokenNonProdAllowedOrgs != null) { + for (String whitelistedOrgId : prodTokenNonProdAllowedOrgs) { if (matchedAPI.getOrganizationId().equalsIgnoreCase(whitelistedOrgId)) { return; } From c5d5968605b2aca5c079d1beac1424a8a654cb22 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 10:14:14 +0530 Subject: [PATCH 04/11] Adding a hashset for performance --- .../security/jwt/JWTAuthenticator.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index d2b5aa3c26..99ff1d0d38 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -62,13 +62,7 @@ import java.nio.charset.StandardCharsets; import java.text.ParseException; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - +import java.util.*; /** * Implements the authenticator interface to authenticate request using a JWT token. @@ -79,14 +73,12 @@ public class JWTAuthenticator implements Authenticator { private final JWTValidator jwtValidator = new JWTValidator(); private final boolean isGatewayTokenCacheEnabled; private AbstractAPIMgtGatewayJWTGenerator jwtGenerator; - private static final String[] prodTokenNonProdAllowedOrgs; + private static final HashSet prodTokenNonProdAllowedOrgs = new HashSet<>(); static { if (System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS") != null) { - prodTokenNonProdAllowedOrgs = - System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS").split("\\s+"); - } else { - prodTokenNonProdAllowedOrgs = null; + Collections.addAll(prodTokenNonProdAllowedOrgs, + System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS").split("\\s+")); } } @@ -418,11 +410,9 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { - if (prodTokenNonProdAllowedOrgs != null) { - for (String whitelistedOrgId : prodTokenNonProdAllowedOrgs) { - if (matchedAPI.getOrganizationId().equalsIgnoreCase(whitelistedOrgId)) { - return; - } + if (!prodTokenNonProdAllowedOrgs.isEmpty()) { + if (prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { + return; } throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, From 939c2cb0172ae5e80bb07d98f389061f2bf450bd Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 10:16:46 +0530 Subject: [PATCH 05/11] Adding a hashset for performance --- .../choreo/connect/enforcer/security/jwt/JWTAuthenticator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 99ff1d0d38..ce53819741 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -73,7 +73,7 @@ public class JWTAuthenticator implements Authenticator { private final JWTValidator jwtValidator = new JWTValidator(); private final boolean isGatewayTokenCacheEnabled; private AbstractAPIMgtGatewayJWTGenerator jwtGenerator; - private static final HashSet prodTokenNonProdAllowedOrgs = new HashSet<>(); + private static final Set prodTokenNonProdAllowedOrgs = new HashSet<>(); static { if (System.getenv("PROD_TOKEN_NONPROD_ALLOWED_ORGS") != null) { From 6b7f12b4abe4940716103ec0ea3a7ef97f487a60 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 10:31:40 +0530 Subject: [PATCH 06/11] Removing java.util.* import --- .../connect/enforcer/security/jwt/JWTAuthenticator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index ce53819741..3edc5ceda4 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -62,7 +62,13 @@ import java.nio.charset.StandardCharsets; import java.text.ParseException; -import java.util.*; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Map; +import java.util.UUID; +import java.util.Date; /** * Implements the authenticator interface to authenticate request using a JWT token. From 02dd7be015533f6ba6f14d89989e6e09655307f6 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 10:47:49 +0530 Subject: [PATCH 07/11] Import order re-order --- .../connect/enforcer/security/jwt/JWTAuthenticator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 3edc5ceda4..c938b01780 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -63,12 +63,12 @@ import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Collections; +import java.util.Date; import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.Map; +import java.util.Set; import java.util.UUID; -import java.util.Date; /** * Implements the authenticator interface to authenticate request using a JWT token. From b58e66a26d0aa36c58ef5683b1063dcf389cb4d8 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 12:07:04 +0530 Subject: [PATCH 08/11] Moving log.info --- .../connect/enforcer/security/jwt/JWTAuthenticator.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index c938b01780..01ebcf6218 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -416,6 +416,8 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { + log.info("Deprecated: Production access token is used to access sandbox API deployment in " + + "organization : " + matchedAPI.getOrganizationId()); if (!prodTokenNonProdAllowedOrgs.isEmpty()) { if (prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { return; @@ -424,9 +426,6 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT_ERROR_MESSAGE); } - - log.info("Deprecated: Production access token is used to access sandbox API deployment in " + - "organization : " + matchedAPI.getOrganizationId()); return; } From 340b7f1674671f0206257537f3e417fa6572526d Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 14:36:23 +0530 Subject: [PATCH 09/11] Update enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java Co-authored-by: Malintha Amarasinghe --- .../connect/enforcer/security/jwt/JWTAuthenticator.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 01ebcf6218..8731a693e3 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -416,16 +416,13 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { - log.info("Deprecated: Production access token is used to access sandbox API deployment in " + - "organization : " + matchedAPI.getOrganizationId()); - if (!prodTokenNonProdAllowedOrgs.isEmpty()) { - if (prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { - return; - } + if (!prodTokenNonProdAllowedOrgs.isEmpty() && !prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT_ERROR_MESSAGE); } + log.info("Deprecated: Production access token is used to access sandbox API deployment in " + + "organization : " + matchedAPI.getOrganizationId()); return; } From 26b610cd09da5aed74f9a301c398f5a7640e9b7a Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 14:56:36 +0530 Subject: [PATCH 10/11] Moving log.info --- .../enforcer/security/jwt/JWTAuthenticator.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 01ebcf6218..0b052d50ab 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -416,16 +416,14 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { - log.info("Deprecated: Production access token is used to access sandbox API deployment in " + - "organization : " + matchedAPI.getOrganizationId()); - if (!prodTokenNonProdAllowedOrgs.isEmpty()) { - if (prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { - return; - } + if (!prodTokenNonProdAllowedOrgs.isEmpty() && + !prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT_ERROR_MESSAGE); } + log.info("Deprecated: Production access token is used to access sandbox API deployment in " + + "organization : " + matchedAPI.getOrganizationId()); return; } From e1f7e767eac42db003ac3e8f7ce9f2c0d1143682 Mon Sep 17 00:00:00 2001 From: rashm1n Date: Mon, 8 Jan 2024 15:14:00 +0530 Subject: [PATCH 11/11] fixing linting issue --- .../choreo/connect/enforcer/security/jwt/JWTAuthenticator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java index 8731a693e3..0b052d50ab 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/JWTAuthenticator.java @@ -416,7 +416,8 @@ private void checkTokenEnvAgainstDeploymentType(String keyType, APIConfig matche if (System.getenv("DEPLOYMENT_TYPE_ENFORCED") != null && System.getenv("DEPLOYMENT_TYPE_ENFORCED").equalsIgnoreCase("false") && keyType.equalsIgnoreCase(APIConstants.JwtTokenConstants.PRODUCTION_KEY_TYPE)) { - if (!prodTokenNonProdAllowedOrgs.isEmpty() && !prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { + if (!prodTokenNonProdAllowedOrgs.isEmpty() && + !prodTokenNonProdAllowedOrgs.contains(matchedAPI.getOrganizationId())) { throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT, APISecurityConstants.API_AUTH_INVALID_ENVIRONMENT_ERROR_MESSAGE);