diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/Utils.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/Utils.java index 89dab46975..c5d440f1b7 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/Utils.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/api/Utils.java @@ -25,10 +25,8 @@ import org.wso2.choreo.connect.enforcer.commons.model.RequestContext; import org.wso2.choreo.connect.enforcer.commons.model.ResourceConfig; import org.wso2.choreo.connect.enforcer.commons.model.RetryConfig; -import org.wso2.choreo.connect.enforcer.commons.model.SecuritySchemaConfig; import org.wso2.choreo.connect.enforcer.config.ConfigHolder; import org.wso2.choreo.connect.enforcer.config.dto.AuthHeaderDto; -import org.wso2.choreo.connect.enforcer.constants.APIConstants; import org.wso2.choreo.connect.enforcer.constants.Constants; import org.wso2.choreo.connect.enforcer.util.FilterUtils; @@ -94,28 +92,6 @@ static void populateRemoveAndProtectedHeaders(RequestContext requestContext) { return; } - Map securitySchemeDefinitions = requestContext.getMatchedAPI() - .getSecuritySchemeDefinitions(); - // API key headers are considered to be protected headers, such that the header - // would not be sent - // to backend and traffic manager. - // This would prevent leaking credentials, even if user is invoking unsecured - // resource with some - // credentials. - for (Map.Entry entry : securitySchemeDefinitions.entrySet()) { - SecuritySchemaConfig schema = entry.getValue(); - if (APIConstants.SWAGGER_API_KEY_AUTH_TYPE_NAME.equalsIgnoreCase(schema.getType())) { - if (APIConstants.SWAGGER_API_KEY_IN_HEADER.equals(schema.getIn())) { - requestContext.getProtectedHeaders().add(schema.getName()); - requestContext.getRemoveHeaders().add(schema.getName()); - continue; - } - if (APIConstants.SWAGGER_API_KEY_IN_QUERY.equals(schema.getIn())) { - requestContext.getQueryParamsToRemove().add(schema.getName()); - } - } - } - // Internal-Key credential is considered to be protected headers, such that the // header would not be sent // to backend and traffic manager. diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/AuthFilter.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/AuthFilter.java index 7721b6eaea..0418fc7a47 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/AuthFilter.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/AuthFilter.java @@ -34,7 +34,6 @@ import org.wso2.choreo.connect.enforcer.constants.InterceptorConstants; import org.wso2.choreo.connect.enforcer.exception.APISecurityException; import org.wso2.choreo.connect.enforcer.security.jwt.APIKeyAuthenticator; -import org.wso2.choreo.connect.enforcer.security.jwt.ChoreoAPIKeyAuthenticator; import org.wso2.choreo.connect.enforcer.security.jwt.InternalAPIKeyAuthenticator; import org.wso2.choreo.connect.enforcer.security.jwt.JWTAuthenticator; import org.wso2.choreo.connect.enforcer.security.jwt.UnsecuredAPIAuthenticator; @@ -67,7 +66,6 @@ private void initializeAuthenticators(APIConfig apiConfig) { boolean isApiKeyProtected = false; boolean isMutualSSLMandatory = false; boolean isOAuthBasicAuthMandatory = false; - boolean isChoreoApiKeyProtected = false; // Set security conditions if (apiConfig.getSecuritySchemeDefinitions() == null) { @@ -88,7 +86,6 @@ private void initializeAuthenticators(APIConfig apiConfig) { equalsIgnoreCase(APIConstants.API_SECURITY_OAUTH_BASIC_AUTH_API_KEY_MANDATORY)) { isOAuthBasicAuthMandatory = true; } else if (apiSecurityLevel.trim().equalsIgnoreCase(APIConstants.SWAGGER_API_KEY_AUTH_TYPE_NAME)) { - isChoreoApiKeyProtected = true; isApiKeyProtected = true; } } @@ -105,11 +102,6 @@ private void initializeAuthenticators(APIConfig apiConfig) { authenticators.add(apiKeyAuthenticator); } - if (isChoreoApiKeyProtected) { - ChoreoAPIKeyAuthenticator choreoAPIKeyAuthenticator = new ChoreoAPIKeyAuthenticator(); - authenticators.add(choreoAPIKeyAuthenticator); - } - Authenticator authenticator = new InternalAPIKeyAuthenticator( ConfigHolder.getInstance().getConfig().getAuthHeader().getTestConsoleHeaderName().toLowerCase()); authenticators.add(authenticator); diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/APIKeyAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/APIKeyAuthenticator.java index 6e68ca5deb..496a477c54 100644 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/APIKeyAuthenticator.java +++ b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/APIKeyAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -18,449 +18,80 @@ package org.wso2.choreo.connect.enforcer.security.jwt; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; -import org.apache.commons.lang3.StringUtils; +import net.minidev.json.JSONValue; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.wso2.carbon.apimgt.common.gateway.dto.JWTConfigurationDto; -import org.wso2.carbon.apimgt.common.gateway.dto.JWTInfoDto; -import org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo; -import org.wso2.carbon.apimgt.common.gateway.jwtgenerator.AbstractAPIMgtGatewayJWTGenerator; -import org.wso2.choreo.connect.enforcer.common.CacheProvider; import org.wso2.choreo.connect.enforcer.commons.model.AuthenticationContext; import org.wso2.choreo.connect.enforcer.commons.model.RequestContext; -import org.wso2.choreo.connect.enforcer.commons.model.SecuritySchemaConfig; import org.wso2.choreo.connect.enforcer.config.ConfigHolder; -import org.wso2.choreo.connect.enforcer.config.EnforcerConfig; -import org.wso2.choreo.connect.enforcer.config.dto.ExtendedTokenIssuerDto; import org.wso2.choreo.connect.enforcer.constants.APIConstants; import org.wso2.choreo.connect.enforcer.constants.APISecurityConstants; -import org.wso2.choreo.connect.enforcer.constants.Constants; -import org.wso2.choreo.connect.enforcer.constants.GeneralErrorCodeConstants; -import org.wso2.choreo.connect.enforcer.constants.HttpConstants; -import org.wso2.choreo.connect.enforcer.dto.APIKeyValidationInfoDTO; -import org.wso2.choreo.connect.enforcer.dto.JWTTokenPayloadInfo; import org.wso2.choreo.connect.enforcer.exception.APISecurityException; -import org.wso2.choreo.connect.enforcer.keymgt.KeyManagerHolder; -import org.wso2.choreo.connect.enforcer.security.KeyValidator; -import org.wso2.choreo.connect.enforcer.util.BackendJwtUtils; -import org.wso2.choreo.connect.enforcer.util.FilterUtils; -import org.wso2.choreo.connect.enforcer.util.JWTUtils; -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.text.ParseException; -import java.util.Arrays; +import java.util.Base64; import java.util.Map; -import java.util.stream.Collectors; /** - * Extends the APIKeyHandler to authenticate request using API Key. + * API Key authenticator. */ -public class APIKeyAuthenticator extends APIKeyHandler { +public class APIKeyAuthenticator extends JWTAuthenticator { private static final Logger log = LogManager.getLogger(APIKeyAuthenticator.class); - private AbstractAPIMgtGatewayJWTGenerator jwtGenerator; - private final boolean isGatewayTokenCacheEnabled; - private boolean apiKeySubValidationEnabled = false; - private static final int IPV4_ADDRESS_BIT_LENGTH = 32; - private static final int IPV6_ADDRESS_BIT_LENGTH = 128; + private static boolean isAPIKeyEnabled = false; + + static { + if (System.getenv("API_KEY_ENABLED") != null) { + isAPIKeyEnabled = Boolean.parseBoolean(System.getenv("API_KEY_ENABLED")); + } + } public APIKeyAuthenticator() { + super(); log.debug("API key authenticator initialized."); - EnforcerConfig enforcerConfig = ConfigHolder.getInstance().getConfig(); - this.isGatewayTokenCacheEnabled = enforcerConfig.getCacheDto().isEnabled(); - if (enforcerConfig.getJwtConfigurationDto().isEnabled()) { - this.jwtGenerator = BackendJwtUtils.getApiMgtGatewayJWTGenerator(); - } - Map tokenIssuers = KeyManagerHolder.getInstance().getTokenIssuerMap() - .get(APIConstants.SUPER_TENANT_DOMAIN_NAME); - for (ExtendedTokenIssuerDto tokenIssuer: tokenIssuers.values()) { - if (APIConstants.KeyManager.APIM_PUBLISHER_ISSUER.equals(tokenIssuer.getName())) { - apiKeySubValidationEnabled = tokenIssuer.isValidateSubscriptions(); - break; - } - } } @Override public boolean canAuthenticate(RequestContext requestContext) { - return isAPIKey(getAPIKeyFromRequest(requestContext)); - } - - // Gets API key from request - private static String getAPIKeyFromRequest(RequestContext requestContext) { - Map securitySchemaDefinitions = requestContext.getMatchedAPI(). - getSecuritySchemeDefinitions(); - // loop over resource security and get definition for the matching security definition name - for (String securityDefinitionName : requestContext.getMatchedResourcePath() - .getSecuritySchemas().keySet()) { - if (securitySchemaDefinitions.containsKey(securityDefinitionName)) { - SecuritySchemaConfig securitySchemaDefinition = - securitySchemaDefinitions.get(securityDefinitionName); - if (APIConstants.SWAGGER_API_KEY_AUTH_TYPE_NAME.equalsIgnoreCase( - securitySchemaDefinition.getType())) { - // If Defined in openAPI definition (when not enabled at APIM App level), - // key must exist in specified location - if (APIConstants.SWAGGER_API_KEY_IN_HEADER.equalsIgnoreCase(securitySchemaDefinition.getIn())) { - if (requestContext.getHeaders().containsKey(securitySchemaDefinition.getName())) { - return requestContext.getHeaders().get(securitySchemaDefinition.getName()); - } - } - if (APIConstants.SWAGGER_API_KEY_IN_QUERY.equalsIgnoreCase(securitySchemaDefinition.getIn())) { - if (requestContext.getQueryParameters().containsKey(securitySchemaDefinition.getName())) { - return requestContext.getQueryParameters().get(securitySchemaDefinition.getName()); - } - } - } - } - } - // If an API Key is not found, check for the API Key in the WebSocket protocol - // header - if (requestContext.getMatchedAPI().getApiType().equalsIgnoreCase(APIConstants.ApiType.WEB_SOCKET) && - requestContext.getHeaders().containsKey(HttpConstants.WEBSOCKET_PROTOCOL_HEADER)) { - String apiKey = extractAPIKeyInWSProtocolHeader(requestContext); - if (apiKey != null && !apiKey.isEmpty()) { - String protocols = getProtocolsToSetInRequestHeaders(requestContext); - if (protocols != null) { - requestContext.addOrModifyHeaders(HttpConstants.WEBSOCKET_PROTOCOL_HEADER, protocols); - } - return apiKey.trim(); - } + if (!isAPIKeyEnabled) { + return false; } - - return ""; + String apiKeyValue = getAPIKeyFromRequest(requestContext); + return apiKeyValue != null && apiKeyValue.startsWith(APIKeyConstants.API_KEY_PREFIX); } @Override public AuthenticationContext authenticate(RequestContext requestContext) throws APISecurityException { - if (requestContext.getMatchedAPI() == null) { - log.debug("API Key Authentication failed"); - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), - APISecurityConstants.API_AUTH_GENERAL_ERROR, - APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE); - } - try { - String apiKey = getAPIKeyFromRequest(requestContext); - String[] splitToken = apiKey.split("\\."); - - SignedJWT signedJWT = SignedJWT.parse(apiKey); - JWSHeader jwsHeader = signedJWT.getHeader(); - JWTClaimsSet payload = signedJWT.getJWTClaimsSet(); - - String apiVersion = requestContext.getMatchedAPI().getVersion(); - String apiContext = requestContext.getMatchedAPI().getBasePath(); - String apiUuid = requestContext.getMatchedAPI().getUuid(); - - // Avoids using internal API keys, when internal key header or queryParam configured as api_key - if (isInternalKey(payload)) { - log.error("Invalid API Key token type. {} ", FilterUtils.getMaskedToken(splitToken[0])); - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), - APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, - APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE); - } - - // Gives jti (also used to populate authentication context) - String tokenIdentifier = payload.getJWTID(); - - // Checks whether key contains in revoked map. - checkInRevokedMap(tokenIdentifier, splitToken); - - // Verifies the token if it is found in cache - JWTTokenPayloadInfo jwtTokenPayloadInfo = (JWTTokenPayloadInfo) - CacheProvider.getGatewayAPIKeyDataCache().getIfPresent(tokenIdentifier); - boolean isVerified = isVerifiedApiKeyInCache(tokenIdentifier, apiKey, payload, splitToken, - "API Key", jwtTokenPayloadInfo); - - // Verifies token when it is not found in cache - if (!isVerified) { - isVerified = verifyTokenWhenNotInCache(jwsHeader, signedJWT, splitToken, payload, "API Key"); - } - - if (isVerified) { - log.debug("API Key signature is verified."); - - if (jwtTokenPayloadInfo == null) { - log.debug("API Key payload not found in the cache."); - - jwtTokenPayloadInfo = new JWTTokenPayloadInfo(); - jwtTokenPayloadInfo.setPayload(payload); - jwtTokenPayloadInfo.setAccessToken(apiKey); - CacheProvider.getGatewayAPIKeyDataCache().put(tokenIdentifier, jwtTokenPayloadInfo); - } - - validateAPIKeyRestrictions(payload, requestContext, apiContext, apiVersion); - APIKeyValidationInfoDTO validationInfoDto; - if (apiKeySubValidationEnabled) { - validationInfoDto = KeyValidator.validateSubscription(requestContext.getMatchedAPI(), payload); - } else { - validationInfoDto = getAPIKeyValidationDTO(requestContext, payload); - } - - if (!validationInfoDto.isAuthorized()) { - if (GeneralErrorCodeConstants.API_BLOCKED_CODE == validationInfoDto - .getValidationStatus()) { - requestContext.getProperties().put(APIConstants.MessageFormat.ERROR_MESSAGE, - GeneralErrorCodeConstants.API_BLOCKED_MESSAGE); - requestContext.getProperties().put(APIConstants.MessageFormat.ERROR_DESCRIPTION, - GeneralErrorCodeConstants.API_BLOCKED_DESCRIPTION); - throw new APISecurityException(APIConstants.StatusCodes.SERVICE_UNAVAILABLE - .getCode(), validationInfoDto.getValidationStatus(), - GeneralErrorCodeConstants.API_BLOCKED_MESSAGE); - } - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), - validationInfoDto.getValidationStatus(), - "User is NOT authorized to access the Resource. " - + "API Subscription validation failed."); - } - - log.debug("API Key authentication successful."); - - // TODO: Add analytics data processing - - // Get SignedJWTInfo - SignedJWTInfo signedJWTInfo = JWTUtils.getSignedJwt(apiKey); - - // Get JWTValidationInfo - JWTValidationInfo validationInfo = new JWTValidationInfo(); - validationInfo.setUser(payload.getSubject()); - - // Generate or get backend JWT - String endUserToken = null; - JWTConfigurationDto jwtConfigurationDto = ConfigHolder.getInstance(). - getConfig().getJwtConfigurationDto(); - if (jwtConfigurationDto.isEnabled() && requestContext.getMatchedAPI().isEnableBackendJWT()) { - JWTInfoDto jwtInfoDto = FilterUtils - .generateJWTInfoDto(null, validationInfo, validationInfoDto, requestContext); - endUserToken = BackendJwtUtils.generateAndRetrieveJWTToken(jwtGenerator, tokenIdentifier, - jwtInfoDto, isGatewayTokenCacheEnabled); - // Set generated jwt token as a response header - requestContext.addOrModifyHeaders(jwtConfigurationDto.getJwtHeader(), endUserToken); - } - - // Create authentication context - JWTClaimsSet claims = signedJWTInfo.getJwtClaimsSet(); - AuthenticationContext authenticationContext = FilterUtils - .generateAuthenticationContext(requestContext, tokenIdentifier, validationInfo, - validationInfoDto, endUserToken, apiKey, false); - if (claims.getClaim("keytype") != null) { - authenticationContext.setKeyType(claims.getClaim("keytype").toString()); - } - log.debug("Analytics data processing for API Key (jti) {} was successful", tokenIdentifier); - return authenticationContext; - - } - } catch (ParseException e) { - log.warn("API Key authentication failed. ", e); - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), - APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, - "API key authentication failed."); - } - log.warn("API Key authentication failed."); - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), - APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, - "API key authentication failed."); - } - - private APIKeyValidationInfoDTO getAPIKeyValidationDTO(RequestContext requestContext, JWTClaimsSet payload) - throws ParseException, APISecurityException { - - APIKeyValidationInfoDTO validationInfoDTO = new APIKeyValidationInfoDTO(); - JSONObject app = payload.getJSONObjectClaim(APIConstants.JwtTokenConstants.APPLICATION); - JSONObject api = null; - if (payload.getClaim(APIConstants.JwtTokenConstants.KEY_TYPE) != null) { - validationInfoDTO.setType(payload.getStringClaim(APIConstants.JwtTokenConstants.KEY_TYPE)); - } else { - validationInfoDTO.setType(APIConstants.API_KEY_TYPE_PRODUCTION); - } - if (app != null) { - validationInfoDTO.setApplicationId(app.getAsNumber(APIConstants.JwtTokenConstants.APPLICATION_ID) - .intValue()); - validationInfoDTO.setApplicationUUID(app.getAsString(APIConstants.JwtTokenConstants.APPLICATION_UUID)); - validationInfoDTO.setApplicationName(app.getAsString(APIConstants.JwtTokenConstants.APPLICATION_NAME)); - validationInfoDTO.setApplicationTier(app.getAsString(APIConstants.JwtTokenConstants.APPLICATION_TIER)); - validationInfoDTO.setSubscriber(app.getAsString(APIConstants.JwtTokenConstants.APPLICATION_OWNER)); - } - - //check whether name is assigned correctly (This was not populated in JWTAuthenticator) - String name = requestContext.getMatchedAPI().getName(); - String version = requestContext.getMatchedAPI().getVersion(); - validationInfoDTO.setApiName(name); - validationInfoDTO.setApiVersion(version); - - if (payload.getClaim(APIConstants.JwtTokenConstants.SUBSCRIBED_APIS) != null) { - // Subscription validation - JSONArray subscribedAPIs = - (JSONArray) payload.getClaim(APIConstants.JwtTokenConstants.SUBSCRIBED_APIS); - for (Object apiObj : subscribedAPIs) { - JSONObject subApi = - (JSONObject) apiObj; - if (name.equals(subApi.getAsString(APIConstants.JwtTokenConstants.API_NAME)) && - version.equals(subApi.getAsString(APIConstants.JwtTokenConstants.API_VERSION) - )) { - api = subApi; - validationInfoDTO.setAuthorized(true); - - //set throttling attributes if present - String subTier = subApi.getAsString(APIConstants.JwtTokenConstants.SUBSCRIPTION_TIER); - String subPublisher = subApi.getAsString(APIConstants.JwtTokenConstants.API_PUBLISHER); - String subTenant = subApi.getAsString(APIConstants.JwtTokenConstants.SUBSCRIBER_TENANT_DOMAIN); - if (subTier != null) { - validationInfoDTO.setTier(subTier); - AuthenticatorUtils.populateTierInfo(validationInfoDTO, payload, subTier); - } - if (subPublisher != null) { - validationInfoDTO.setApiPublisher(subPublisher); - } - if (subTenant != null) { - validationInfoDTO.setSubscriberTenantDomain(subTenant); - } - - log.debug("APIKeyValidationInfoDTO populated for API: {}, version: {}.", name, version); - - break; - } - } - if (api == null) { - log.debug("Subscription data not populated in APIKeyValidationInfoDTO for the API: {}, version: {}.", - name, version); - log.error("User's subscription details cannot obtain for the API : {}", name); - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), - APISecurityConstants.API_AUTH_FORBIDDEN, - APISecurityConstants.API_AUTH_FORBIDDEN_MESSAGE); - } - } - return validationInfoDTO; + return super.authenticate(requestContext); } - private void validateAPIKeyRestrictions(JWTClaimsSet payload, RequestContext requestContext, String apiContext, - String apiVersion) throws APISecurityException { - String permittedIPList = null; - if (payload.getClaim(APIConstants.JwtTokenConstants.PERMITTED_IP) != null) { - permittedIPList = (String) payload.getClaim(APIConstants.JwtTokenConstants.PERMITTED_IP); - } - - if (StringUtils.isNotEmpty(permittedIPList)) { - // Validate client IP against permitted IPs - String clientIP = requestContext.getClientIp(); - - if (StringUtils.isNotEmpty(clientIP)) { - for (String restrictedIP : permittedIPList.split(",")) { - if (isIpInNetwork(clientIP, restrictedIP.trim())) { - // Client IP is allowed - return; - } - } - if (StringUtils.isNotEmpty(clientIP)) { - log.debug("Invocations to API: {}:{} is not permitted for client with IP: {}", - apiContext, apiVersion, clientIP); - } - - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), - APISecurityConstants.API_AUTH_FORBIDDEN, APISecurityConstants.API_AUTH_FORBIDDEN_MESSAGE); - } - - } - - String permittedRefererList = null; - if (payload.getClaim(APIConstants.JwtTokenConstants.PERMITTED_REFERER) != null) { - permittedRefererList = (String) payload.getClaim(APIConstants.JwtTokenConstants.PERMITTED_REFERER); - } - if (StringUtils.isNotEmpty(permittedRefererList)) { - // Validate http referer against the permitted referrers - Map transportHeaderMap = requestContext.getHeaders(); - if (transportHeaderMap != null) { - String referer = transportHeaderMap.get("referer"); - if (StringUtils.isNotEmpty(referer)) { - for (String restrictedReferer : permittedRefererList.split(",")) { - String restrictedRefererRegExp = restrictedReferer.trim() - .replace("*", "[^ ]*"); - if (referer.matches(restrictedRefererRegExp)) { - // Referer is allowed - return; - } - } - if (StringUtils.isNotEmpty(referer)) { - log.debug("Invocations to API: {}:{} is not permitted for referer: {}", - apiContext, apiVersion, referer); - } - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), - APISecurityConstants.API_AUTH_FORBIDDEN, APISecurityConstants.API_AUTH_FORBIDDEN_MESSAGE); - } else { - throw new APISecurityException(APIConstants.StatusCodes.UNAUTHORIZED.getCode(), - APISecurityConstants.API_AUTH_FORBIDDEN, APISecurityConstants.API_AUTH_FORBIDDEN_MESSAGE); - } - } - } + private String getAPIKeyFromRequest(RequestContext requestContext) { + Map headers = requestContext.getHeaders(); + return headers.get(ConfigHolder.getInstance().getConfig().getApiKeyConfig() + .getApiKeyInternalHeader().toLowerCase()); } - private boolean isIpInNetwork(String ip, String cidr) { - - if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(cidr)) { - return false; - } - ip = ip.trim(); - cidr = cidr.trim(); - - if (cidr.contains("/")) { - String[] cidrArr = cidr.split("/"); - if (cidrArr.length < 2 || (ip.contains(".") && !cidr.contains(".")) || - (ip.contains(":") && !cidr.contains(":"))) { - return false; - } - - BigInteger netAddress = ipToBigInteger(cidrArr[0]); - int netBits = Integer.parseInt(cidrArr[1]); - BigInteger givenIP = ipToBigInteger(ip); - - if (ip.contains(".")) { - // IPv4 - if (netAddress.shiftRight(IPV4_ADDRESS_BIT_LENGTH - netBits) - .shiftLeft(IPV4_ADDRESS_BIT_LENGTH - netBits).compareTo( - givenIP.shiftRight(IPV4_ADDRESS_BIT_LENGTH - netBits) - .shiftLeft(IPV4_ADDRESS_BIT_LENGTH - netBits)) == 0) { - return true; - } - } else if (ip.contains(":")) { - // IPv6 - if (netAddress.shiftRight(IPV6_ADDRESS_BIT_LENGTH - netBits) - .shiftLeft(IPV6_ADDRESS_BIT_LENGTH - netBits).compareTo( - givenIP.shiftRight(IPV6_ADDRESS_BIT_LENGTH - netBits) - .shiftLeft(IPV6_ADDRESS_BIT_LENGTH - netBits)) == 0) { - return true; - } - } - } else if (ip.equals(cidr)) { - return true; - } - return false; - } - - private BigInteger ipToBigInteger(String ipAddress) { + @Override + protected String retrieveTokenFromRequestCtx(RequestContext requestContext) throws APISecurityException { - InetAddress address; try { - address = getAddress(ipAddress); - byte[] bytes = address.getAddress(); - return new BigInteger(1, bytes); - } catch (UnknownHostException e) { - //ignore the error and log it - log.error("Error while parsing host IP {}", ipAddress, e); + String apiKeyHeaderValue = getAPIKeyFromRequest(requestContext).trim(); + // Skipping the prefix(`chk_`) and checksum. + String apiKeyData = apiKeyHeaderValue.substring(4, apiKeyHeaderValue.length() - 6); + // Base 64 decode key data. + String decodedKeyData = new String(Base64.getDecoder().decode(apiKeyData)); + // Convert data into JSON. + JSONObject jsonObject = (JSONObject) JSONValue.parse(decodedKeyData); + // Extracting the jwt token. + return jsonObject.getAsString(APIKeyConstants.API_KEY_JSON_KEY); + } catch (Exception e) { + throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), + APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, + APISecurityConstants.API_AUTH_INVALID_CREDENTIALS_MESSAGE); } - return BigInteger.ZERO; - } - - private InetAddress getAddress(String ipAddress) throws UnknownHostException { - - return InetAddress.getByName(ipAddress); } @Override @@ -470,36 +101,11 @@ public String getChallengeString() { @Override public String getName() { - return "API Key"; + return "Choreo API Key"; } @Override public int getPriority() { - return 30; - } - - public static String extractAPIKeyInWSProtocolHeader(RequestContext requestContext) { - String protocolHeader = requestContext.getHeaders().get( - HttpConstants.WEBSOCKET_PROTOCOL_HEADER); - if (protocolHeader != null) { - String[] secProtocolHeaderValues = protocolHeader.split(","); - if (secProtocolHeaderValues.length > 1 && secProtocolHeaderValues[0].equals( - Constants.WS_API_KEY_IDENTIFIER)) { - AuthenticatorUtils.addWSProtocolResponseHeaderIfRequired(requestContext, - Constants.WS_API_KEY_IDENTIFIER); - return secProtocolHeaderValues[1].trim(); - } - } - return ""; - } - - public static String getProtocolsToSetInRequestHeaders(RequestContext requestContext) { - String[] secProtocolHeaderValues = requestContext.getHeaders().get( - HttpConstants.WEBSOCKET_PROTOCOL_HEADER).split(","); - if (secProtocolHeaderValues.length > 2) { - return Arrays.stream(secProtocolHeaderValues, 2, secProtocolHeaderValues.length) - .collect(Collectors.joining(",")).trim(); - } - return null; + return 15; } } diff --git a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/ChoreoAPIKeyAuthenticator.java b/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/ChoreoAPIKeyAuthenticator.java deleted file mode 100644 index 628aedb471..0000000000 --- a/enforcer-parent/enforcer/src/main/java/org/wso2/choreo/connect/enforcer/security/jwt/ChoreoAPIKeyAuthenticator.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.enforcer.security.jwt; - -import net.minidev.json.JSONObject; -import net.minidev.json.JSONValue; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.wso2.choreo.connect.enforcer.commons.model.AuthenticationContext; -import org.wso2.choreo.connect.enforcer.commons.model.RequestContext; -import org.wso2.choreo.connect.enforcer.config.ConfigHolder; -import org.wso2.choreo.connect.enforcer.exception.APISecurityException; - -import java.util.Base64; -import java.util.Map; - -/** - * API Key authenticator. - */ -public class ChoreoAPIKeyAuthenticator extends JWTAuthenticator { - - private static final Logger log = LogManager.getLogger(ChoreoAPIKeyAuthenticator.class); - - private static boolean isAPIKeyEnabled = false; - - static { - if (System.getenv("API_KEY_ENABLED") != null) { - isAPIKeyEnabled = Boolean.parseBoolean(System.getenv("API_KEY_ENABLED")); - } - } - - public ChoreoAPIKeyAuthenticator() { - super(); - log.debug("API key authenticator initialized."); - } - - @Override - public boolean canAuthenticate(RequestContext requestContext) { - - if (!isAPIKeyEnabled) { - return false; - } - String apiKeyValue = getAPIKeyFromRequest(requestContext); - return apiKeyValue != null && apiKeyValue.startsWith(APIKeyConstants.API_KEY_PREFIX); - } - - @Override - public AuthenticationContext authenticate(RequestContext requestContext) throws APISecurityException { - - return super.authenticate(requestContext); - } - - private String getAPIKeyFromRequest(RequestContext requestContext) { - Map headers = requestContext.getHeaders(); - return headers.get(ConfigHolder.getInstance().getConfig().getApiKeyConfig() - .getApiKeyInternalHeader().toLowerCase()); - } - - @Override - protected String retrieveTokenFromRequestCtx(RequestContext requestContext) { - - String apiKeyHeaderValue = getAPIKeyFromRequest(requestContext); - // Skipping the prefix(`chk_`) and checksum. - String apiKeyData = apiKeyHeaderValue.substring(4, apiKeyHeaderValue.length() - 6); - // Base 64 decode key data. - String decodedKeyData = new String(Base64.getDecoder().decode(apiKeyData)); - // Convert data into JSON. - JSONObject jsonObject = (JSONObject) JSONValue.parse(decodedKeyData); - // Extracting the jwt token. - return jsonObject.getAsString(APIKeyConstants.API_KEY_JSON_KEY); - } - - @Override - public String getChallengeString() { - return ""; - } - - @Override - public String getName() { - return "Choreo API Key"; - } - - @Override - public int getPriority() { - return 15; - } -} 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 b798dd6af6..925f3e4763 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 @@ -526,8 +526,8 @@ protected String retrieveTokenFromRequestCtx(RequestContext requestContext) thro throw new APISecurityException(APIConstants.StatusCodes.UNAUTHENTICATED.getCode(), APISecurityConstants.API_AUTH_MISSING_CREDENTIALS, "Missing Credentials"); } - String[] splitToken = authHeaderVal.split("\\s"); - String token = authHeaderVal; + String token = authHeaderVal.trim(); + String[] splitToken = token.split("\\s"); // Extract the token when it is sent as bearer token. i.e Authorization: Bearer if (splitToken.length > 1) { token = splitToken[1]; diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/standalone/security/APIKeyTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/standalone/security/APIKeyTestCase.java deleted file mode 100644 index e558ce152a..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/standalone/security/APIKeyTestCase.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.standalone.security; - -import com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus; -import org.testng.Assert; -import org.testng.annotations.Test; -import org.wso2.choreo.connect.mockbackend.ResponseConstants; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.common.model.API; -import org.wso2.choreo.connect.tests.common.model.ApplicationDTO; -import org.wso2.choreo.connect.tests.util.*; - -import java.util.HashMap; -import java.util.Map; - -public class APIKeyTestCase extends ApimBaseTest { - private String testAPIKey = - "eyJ4NXQiOiJOVGRtWmpNNFpEazNOalkwWXpjNU1tWm1PRGd3TVRFM01XWXdOREU1TVdSbFpEZzROemM0WkE9PSIsImtpZCI6Imdhd" + - "GV3YXlfY2VydGlmaWNhdGVfYWxpYXMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbkBjYXJib" + - "24uc3VwZXIiLCJhcHBsaWNhdGlvbiI6eyJvd25lciI6ImFkbWluIiwidGllclF1b3RhVHlwZSI6bnVsbCwidGllciI6Il" + - "VubGltaXRlZCIsIm5hbWUiOiJBUElLZXlUZXN0QXBwIiwiaWQiOjg4LCJ1dWlkIjoiYzcwZmVmZjEtYWZhOS00YTA3LTk" + - "0OWEtNjIwNDExZjFjZmVhIn0sImlzcyI6Imh0dHBzOlwvXC9hcGltOjk0NDNcL29hdXRoMlwvdG9rZW4iLCJ0aWVySW5m" + - "byI6eyJVbmxpbWl0ZWQiOnsidGllclF1b3RhVHlwZSI6InJlcXVlc3RDb3VudCIsImdyYXBoUUxNYXhDb21wbGV4aXR5I" + - "jowLCJncmFwaFFMTWF4RGVwdGgiOjAsInN0b3BPblF1b3RhUmVhY2giOnRydWUsInNwaWtlQXJyZXN0TGltaXQiOjAsIn" + - "NwaWtlQXJyZXN0VW5pdCI6bnVsbH19LCJrZXl0eXBlIjoiUFJPRFVDVElPTiIsInN1YnNjcmliZWRBUElzIjpbeyJzdWJ" + - "zY3JpYmVyVGVuYW50RG9tYWluIjoiY2FyYm9uLnN1cGVyIiwibmFtZSI6IkFQSUtleVRlc3RBUEkiLCJjb250ZXh0Ijoi" + - "XC9hcGlLZXlcLzEuMC4wIiwicHVibGlzaGVyIjoiYWRtaW4iLCJ2ZXJzaW9uIjoiMS4wLjAiLCJzdWJzY3JpcHRpb25Ua" + - "WVyIjoiVW5saW1pdGVkIn1dLCJ0b2tlbl90eXBlIjoiYXBpS2V5IiwiaWF0IjoxNjM4MzUzOTA1LCJqdGkiOiJkNjlmND" + - "JlNy1mNWExLTRiZDktOTFjZC0zZmZjYjg5NGQ1OTgifQ==.T_V3sqMPSP3sD4a91HM4dbucac-J9PazE0xkv85D2i5V8p" + - "oj1H9jBaAWLH1PRdDdPpGuV69px3cRKJugyZ43z8DrAwYsMO4DzC_VYAJjAFCHWwg82vjeLC3gQrv0A85cx1p4jyjWAbx" + - "ByLO4351G96ds-yMfKaUF1ZYWzDtnsI1SIzgczXY3OLANdjkNwE0wvlu-UOWSdEEFSdNFDYc4Nn33g2EeL4I9llYltW81" + - "weXA0WnOMK4nvKZtrSQmWTIH-RlfJGR07FZRfFeQi3OfQuOR6puYHBx946PqAbIGj5t2IhmaQl_Bun66AJwkd2nalO2bx" + - "pNEHoTWCtuHN2zVpQ=="; - - @Test(description = "Test to check the API Key in query param is working") - public void invokeAPIKeyInQueryParamSuccessTest() throws Exception { - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/pet/1?x-api-key=" + testAPIKey)); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - @Test(description = "Test to check the API Key in query param is working and not work for header") - public void invokeAPIKeyInHeaderParamFailTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("x-api-key", testAPIKey); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/pet/1"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED, "Response code mismatched"); - } - - @Test(description = "Test to check the API Key in api level") - public void invokeAPIKeyAPILevelTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("x-api-key-header", testAPIKey); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/pet/findByTags"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - @Test(description = "Test to check the API Key fails for only oauth2 secured resource") - public void invokeAPIKeyOauth2Test() throws Exception { - Map headers = new HashMap<>(); - headers.put("x-api-key-header", testAPIKey); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/pets/findByTags"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED, "Response code mismatched"); - } - - @Test(description = "Test to check the backend JWT generation for API Key") - public void apiKeyBackendJwtGenerationTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("x-api-key-header", testAPIKey); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/jwtheader"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - Assert.assertEquals(response.getData(), ResponseConstants.VALID_JWT_RESPONSE, - "Response body mismatched"); - } - - @Test(description = "Test to check the oauth2 secured resource") - public void invokeOauth2Test() throws Exception { - API api = new API(); - api.setName("APIKeyTestAPI"); - api.setContext("/apiKey/1.0.0"); - api.setVersion("1.0.0"); - api.setProvider("admin"); - - //Define application info - ApplicationDTO application = new ApplicationDTO(); - application.setName("APIKeyTestApp"); - application.setTier("Unlimited"); - application.setId(88); - String jwtToken = TokenUtil.getJWT(api, application, "Unlimited", TestConstant.KEY_TYPE_PRODUCTION, - 3600, "write:pets", false); - Map headers = new HashMap<>(); - headers.put(TestConstant.AUTHORIZATION_HEADER, "Bearer " + jwtToken); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/pets/findByTags"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/InternalKeyHeaderTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/InternalKeyHeaderTestCase.java deleted file mode 100644 index 4b4020b673..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/InternalKeyHeaderTestCase.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim; - -import com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus; -import org.json.JSONArray; -import org.json.JSONObject; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.publisher.api.ApiResponse; -import org.wso2.am.integration.clients.store.api.v1.dto.APIKeyDTO; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.dto.Application; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.apim.utils.StoreUtils; -import org.wso2.choreo.connect.tests.util.*; - -import java.util.HashMap; -import java.util.Map; - -public class InternalKeyHeaderTestCase extends ApimBaseTest { - - private static final String SAMPLE_API_NAME = "APIKeyHeaderTestAPI"; - private static final String SAMPLE_API_CONTEXT = "apiKeyHeader"; - private static final String SAMPLE_API_VERSION = "1.0.0"; - private static final String APP_NAME = "APIKeyHeaderTestApp"; - - protected String apiKey; - private String endPoint; - private String internalKey; - - @BeforeClass(description = "Initialise the setup for API key tests") - void start() throws Exception { - super.initWithSuperTenant(); - - String targetDir = Utils.getTargetDirPath(); - String filePath = targetDir + ApictlUtils.OPENAPIS_PATH + "api_key_openAPI.yaml"; - - // enable apikey in apim - JSONArray securityScheme = new JSONArray(); - securityScheme.put("oauth_basic_auth_api_key_mandatory"); - securityScheme.put("api_key"); - - JSONObject apiProperties = new JSONObject(); - apiProperties.put("name", SAMPLE_API_NAME); - apiProperties.put("context", "/" + SAMPLE_API_CONTEXT); - apiProperties.put("version", SAMPLE_API_VERSION); - apiProperties.put("provider", user.getUserName()); - apiProperties.put("securityScheme", securityScheme); - String apiId = PublisherUtils.createAPIUsingOAS(apiProperties, filePath, publisherRestClient); - - publisherRestClient.changeAPILifeCycleStatus(apiId, "Publish"); - - //Create and subscribe to app - Application app = new Application(APP_NAME, TestConstant.APPLICATION_TIER.UNLIMITED); - String applicationId = StoreUtils.createApplication(app, storeRestClient); - - PublisherUtils.createAPIRevisionAndDeploy(apiId, publisherRestClient); - - StoreUtils.subscribeToAPI(apiId, applicationId, TestConstant.SUBSCRIPTION_TIER.UNLIMITED, storeRestClient); - - endPoint = Utils.getServiceURLHttps(SAMPLE_API_CONTEXT + "/1.0.0/pet/1"); - - // Obtain internal key - ApiResponse internalApiKeyDTO = - publisherRestClient.generateInternalApiKey(apiId); - internalKey = internalApiKeyDTO.getData().getApikey(); - - // Obtain API key - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - apiKey = apiKeyDTO.getApikey(); - - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - @Test(description = "Test to check the API Key in header is working") - public void invokeAPIKeyWithSimilarHeaderSuccessTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKey); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), - com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK, - "Response code mismatched"); - } - - @Test(description = "Test to check the Internal Key in header is working") - public void invokeInternalAPIKeyWithSimilarHeaderSuccessTest() throws Exception { - // Set header - Map headers = new HashMap<>(); - headers.put("apikey", internalKey); - HttpResponse response = HttpsClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyAppLevelThrottleTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyAppLevelThrottleTestCase.java deleted file mode 100644 index c1015d358d..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyAppLevelThrottleTestCase.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim.apikey; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.admin.ApiException; -import org.wso2.am.integration.clients.admin.ApiResponse; -import org.wso2.am.integration.clients.admin.api.dto.ApplicationThrottlePolicyDTO; -import org.wso2.am.integration.clients.admin.api.dto.RequestCountLimitDTO; -import org.wso2.am.integration.clients.admin.api.dto.ThrottleLimitDTO; -import org.wso2.am.integration.clients.store.api.v1.dto.APIKeyDTO; -import org.wso2.am.integration.test.impl.DtoFactory; -import org.wso2.am.integration.test.utils.bean.APIRequest; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.dto.Application; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.apim.utils.StoreUtils; -import org.wso2.choreo.connect.tests.context.CCTestException; -import org.wso2.choreo.connect.tests.testcases.withapim.throttle.ThrottlingBaseTestCase; -import org.wso2.choreo.connect.tests.util.TestConstant; -import org.wso2.choreo.connect.tests.util.Utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class APIKeyAppLevelThrottleTestCase extends ApimBaseTest { - - private static final String API_NAME = "APIKeyAppLevelThrottleApi"; - private static final String API_CONTEXT = "apikey_app_level_throttling"; - private static final String API_VERSION = "1.0.0"; - private static final String APP_NAME = "apiKeyAppThrottleApp"; - - private static final String POLICY_NAME = "app5PerMin"; - private static final String POLICY_TIME_UNIT = "min"; - private static final Integer POLICY_UNIT_TIME = 1; - private static final long REQUEST_COUNT = 5L; - private static final String POLICY_DESC = "This is an application level throttle policy"; - - private ApplicationThrottlePolicyDTO appThrottlePolicyDTO; - String apiId; - String applicationId; - - @BeforeClass(alwaysRun = true) - public void setEnvironment() throws Exception { - super.initWithSuperTenant(); - - // create the throttling policy DTO with request count limit - RequestCountLimitDTO reqCountLimit = DtoFactory.createRequestCountLimitDTO(POLICY_TIME_UNIT, POLICY_UNIT_TIME, - REQUEST_COUNT); - ThrottleLimitDTO defaultLimit = DtoFactory.createThrottleLimitDTO(ThrottleLimitDTO.TypeEnum.REQUESTCOUNTLIMIT, - reqCountLimit, null); - - // Add the application throttling policy - appThrottlePolicyDTO = DtoFactory.createApplicationThrottlePolicyDTO(POLICY_NAME, POLICY_NAME, - POLICY_DESC, false, defaultLimit); - ApiResponse addedPolicy = adminRestClient.addApplicationThrottlingPolicy( - appThrottlePolicyDTO); - appThrottlePolicyDTO = addedPolicy.getData(); - - // Create API - APIRequest apiRequest = PublisherUtils.createSampleAPIRequest(API_NAME, API_CONTEXT, API_VERSION, user.getUserName()); - - List securityScheme = new ArrayList<>(); - securityScheme.add("oauth_basic_auth_api_key_mandatory"); - securityScheme.add("api_key"); - apiRequest.setSecurityScheme(securityScheme); - - apiId = PublisherUtils.createAndPublishAPI(apiRequest, publisherRestClient); - - // Create the app and subscribe - Application app = new Application(APP_NAME, POLICY_NAME); - applicationId = StoreUtils.createApplication(app, storeRestClient); - StoreUtils.subscribeToAPI(apiId, applicationId, TestConstant.SUBSCRIPTION_TIER.UNLIMITED, - storeRestClient); - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - @Test(description = "Test application level throttling for API Key") - public void testApplicationLevelThrottlingForAPIKey() throws Exception { - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - String apiKey = apiKeyDTO.getApikey(); - Map requestHeaders = new HashMap<>(); - requestHeaders.put("apikey", apiKey); - - String endpointURL = Utils.getServiceURLHttps(API_CONTEXT + "/1.0.0/pet/findByStatus"); - Assert.assertTrue(ThrottlingBaseTestCase.isThrottled(endpointURL, requestHeaders, null, REQUEST_COUNT), - "Request not throttled by request count condition in application tier"); - } - - @AfterClass - public void destroy() throws Exception { - StoreUtils.removeAllSubscriptionsForAnApp(applicationId, storeRestClient); - storeRestClient.removeApplicationById(applicationId); - publisherRestClient.deleteAPI(apiId); - adminRestClient.deleteApplicationThrottlingPolicy(appThrottlePolicyDTO.getPolicyId()); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyBlockedAPITestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyBlockedAPITestCase.java deleted file mode 100644 index 2223105e94..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyBlockedAPITestCase.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim.apikey; - -import com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus; -import org.json.JSONArray; -import org.json.JSONObject; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.store.api.v1.dto.APIKeyDTO; -import org.wso2.am.integration.test.utils.bean.APILifeCycleAction; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.dto.Application; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.apim.utils.StoreUtils; -import org.wso2.choreo.connect.tests.context.CCTestException; -import org.wso2.choreo.connect.tests.util.*; - -import java.util.HashMap; -import java.util.Map; - -public class APIKeyBlockedAPITestCase extends ApimBaseTest { - - private static final String SAMPLE_API_NAME = "APIKeyTestAPI"; - private static final String SAMPLE_API_CONTEXT = "apiKey"; - private static final String SAMPLE_API_VERSION = "1.0.0"; - private static final String APP_NAME = "APIKeyTestApp"; - private String applicationId; - private String apiId; - private String endpointURL; - Map headers = new HashMap<>(); - - @BeforeClass(description = "Initialise the setup for API key App level test case") - void start() throws Exception { - super.initWithSuperTenant(); - - String targetDir = Utils.getTargetDirPath(); - String filePath = targetDir + ApictlUtils.OPENAPIS_PATH + "api_key_openAPI.yaml"; - - JSONArray securityScheme = new JSONArray(); - securityScheme.put("oauth_basic_auth_api_key_mandatory"); - securityScheme.put("api_key"); - - JSONObject apiProperties = new JSONObject(); - apiProperties.put("name", SAMPLE_API_NAME); - apiProperties.put("context", "/" + SAMPLE_API_CONTEXT); - apiProperties.put("version", SAMPLE_API_VERSION); - apiProperties.put("provider", user.getUserName()); - apiProperties.put("securityScheme", securityScheme); - apiId = PublisherUtils.createAPIUsingOAS(apiProperties, filePath, publisherRestClient); - - publisherRestClient.changeAPILifeCycleStatus(apiId, "Publish"); - - // creating the application - Application app = new Application(APP_NAME, TestConstant.APPLICATION_TIER.UNLIMITED); - applicationId = StoreUtils.createApplication(app, storeRestClient); - - PublisherUtils.createAPIRevisionAndDeploy(apiId, publisherRestClient); - - StoreUtils.subscribeToAPI(apiId, applicationId, TestConstant.SUBSCRIPTION_TIER.UNLIMITED, storeRestClient); - - endpointURL = Utils.getServiceURLHttps(SAMPLE_API_CONTEXT + "/1.0.0/pet/1"); - - // Obtain API keys - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - String apiKey = apiKeyDTO.getApikey(); - headers.put("apikey", apiKey); - - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - @Test(description = "Invoke API which has API Key as the Application Level Security") - public void testAPIKeyForAppLevel() throws Exception { - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endpointURL), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), - com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK, - "Response code mismatched"); - } - - @Test(description = "Invoke blocked API and check 700700 error code is received", dependsOnMethods = "testAPIKeyForAppLevel") - public void testAPIKeyForBlockedStateAPI() throws CCTestException, InterruptedException { - PublisherUtils.changeLCStateAPI(apiId, APILifeCycleAction.BLOCK.getAction(), publisherRestClient, false); - Thread.sleep(3000); - HttpResponse response = HttpsClientRequest.doGet(endpointURL, headers); - Assert.assertNotNull(response, "Error occurred while invoking the endpoint " + endpointURL + ". HttpResponse"); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_SERVICE_UNAVAILABLE, - "Expected error code is 503, but received the code : " + response.getResponseCode()); - Assert.assertTrue(response.getData().contains("700700") && response.getData().contains("API blocked"), - "Response message mismatched. Expected the error code 700700, but Response Data: " + response.getData()); - } - - @Test(description = "Re publish the blocked API and invoke API", dependsOnMethods = "testAPIKeyForBlockedStateAPI") - public void testAPIKeyForRePublishedAPI() throws CCTestException, InterruptedException { - PublisherUtils.changeLCStateAPI(apiId, APILifeCycleAction.RE_PUBLISH.getAction(), publisherRestClient, false); - Thread.sleep(3000); - HttpResponse response = HttpsClientRequest.retryGetRequestUntilDeployed(endpointURL, headers); - Assert.assertNotNull(response, "Error occurred while invoking the endpoint " + endpointURL + ". HttpResponse"); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_SUCCESS, - "Valid subscription should be able to invoke the associated API"); - } - - @Test(description = "Send a request after deleting the subscription", dependsOnMethods = "testAPIKeyForRePublishedAPI") - public void testAPIKeyWhenSubscriptionDeleted() throws CCTestException, InterruptedException { - StoreUtils.removeAllSubscriptionsForAnApp(applicationId, storeRestClient); - Thread.sleep(3000); - HttpResponse response = HttpsClientRequest.doGet(endpointURL, headers); - Assert.assertNotNull(response, "Error occurred while invoking the endpoint " + endpointURL + ". HttpResponse"); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_FORBIDDEN, - "Expected error code is 503, but received the code : " + response.getResponseCode()); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeySubLevelThrottleTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeySubLevelThrottleTestCase.java deleted file mode 100644 index 0ee8cb91f5..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeySubLevelThrottleTestCase.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim.apikey; - -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.admin.ApiResponse; -import org.wso2.am.integration.clients.admin.api.dto.RequestCountLimitDTO; -import org.wso2.am.integration.clients.admin.api.dto.SubscriptionThrottlePolicyDTO; -import org.wso2.am.integration.clients.admin.api.dto.ThrottleLimitDTO; -import org.wso2.am.integration.clients.store.api.v1.dto.APIKeyDTO; -import org.wso2.am.integration.test.impl.DtoFactory; -import org.wso2.am.integration.test.utils.bean.APIRequest; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.dto.Application; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.apim.utils.StoreUtils; -import org.wso2.choreo.connect.tests.testcases.withapim.throttle.ThrottlingBaseTestCase; -import org.wso2.choreo.connect.tests.util.TestConstant; -import org.wso2.choreo.connect.tests.util.Utils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class APIKeySubLevelThrottleTestCase extends ApimBaseTest { - - private static final String API_NAME= "APIKeySubLevelThrottleApi"; - private static final String API_CONTEXT = "apikey_sub_level_throttling"; - private static final String API_VERSION = "1.0.0"; - private static final String APP_NAME = "apiKeySubThrottleApp"; - - private static final String POLICY_NAME = "sub5PerMin"; - private static final String POLICY_TIME_UNIT = "min"; - private static final Integer POLICY_UNIT_TIME = 1; - private static final long REQUEST_COUNT = 5L; - private static final String POLICY_DESC = "This is a subscription level throttle policy"; - - private SubscriptionThrottlePolicyDTO subThrottlePolicyDTO; - String apiId; - String applicationId; - - @BeforeClass(alwaysRun = true) - public void setEnvironment() throws Exception { - super.initWithSuperTenant(); - - // create the throttling policy DTO with request count limit - RequestCountLimitDTO reqCountLimit = DtoFactory.createRequestCountLimitDTO(POLICY_TIME_UNIT, POLICY_UNIT_TIME, - REQUEST_COUNT); - ThrottleLimitDTO defaultLimit = DtoFactory.createThrottleLimitDTO(ThrottleLimitDTO.TypeEnum.REQUESTCOUNTLIMIT, - reqCountLimit, null); - - // Add the subscription throttling policy - subThrottlePolicyDTO = DtoFactory.createSubscriptionThrottlePolicyDTO(POLICY_NAME, POLICY_NAME, POLICY_DESC, - false, defaultLimit,-1, -1, 100, - "min", new ArrayList<>(), true, "", 0); - ApiResponse addedSubPolicy = adminRestClient.addSubscriptionThrottlingPolicy( - subThrottlePolicyDTO); - subThrottlePolicyDTO = addedSubPolicy.getData(); - - // Create API - APIRequest apiRequest = PublisherUtils.createSampleAPIRequest(API_NAME, API_CONTEXT, API_VERSION, user.getUserName()); - apiRequest.setTiersCollection(POLICY_NAME); - - List securityScheme = new ArrayList<>(); - securityScheme.add("oauth_basic_auth_api_key_mandatory"); - securityScheme.add("api_key"); - apiRequest.setSecurityScheme(securityScheme); - - apiId = PublisherUtils.createAndPublishAPI(apiRequest, publisherRestClient); - - // Create the app and subscribe - Application app = new Application(APP_NAME, TestConstant.APPLICATION_TIER.UNLIMITED); - applicationId = StoreUtils.createApplication(app, storeRestClient); - StoreUtils.subscribeToAPI(apiId, applicationId, POLICY_NAME, storeRestClient); - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - @Test(description = "Test subscription level throttling for API Key") - public void testSubscriptionLevelThrottlingForAPIKey() throws Exception { - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - String apiKey = apiKeyDTO.getApikey(); - Map requestHeaders = new HashMap<>(); - requestHeaders.put("apikey", apiKey); - - String endpointURL = Utils.getServiceURLHttps(API_CONTEXT + "/1.0.0/pet/findByStatus"); - Assert.assertTrue(ThrottlingBaseTestCase.isThrottled(endpointURL, requestHeaders, null, REQUEST_COUNT), - "Request not throttled by request count condition in application tier"); - } - - @AfterClass - public void destroy() throws Exception { - StoreUtils.removeAllSubscriptionsForAnApp(applicationId, storeRestClient); - storeRestClient.removeApplicationById(applicationId); - publisherRestClient.deleteAPI(apiId); - adminRestClient.deleteSubscriptionThrottlingPolicy(subThrottlePolicyDTO.getPolicyId()); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyTestCase.java deleted file mode 100644 index 9d2e2bb55f..0000000000 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/APIKeyTestCase.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. 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.choreo.connect.tests.testcases.withapim.apikey; - -import org.apache.http.HttpStatus; -import org.json.JSONArray; -import org.json.JSONObject; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; -import org.wso2.am.integration.clients.store.api.v1.dto.APIKeyDTO; -import org.wso2.choreo.connect.mockbackend.ResponseConstants; -import org.wso2.choreo.connect.tests.apim.ApimBaseTest; -import org.wso2.choreo.connect.tests.apim.dto.Application; -import org.wso2.choreo.connect.tests.apim.utils.PublisherUtils; -import org.wso2.choreo.connect.tests.apim.utils.StoreUtils; -import org.wso2.choreo.connect.tests.util.ApictlUtils; -import org.wso2.choreo.connect.tests.util.HttpClientRequest; -import org.wso2.choreo.connect.tests.util.HttpResponse; -import org.wso2.choreo.connect.tests.util.TestConstant; -import org.wso2.choreo.connect.tests.util.Utils; - -import java.util.*; - -public class APIKeyTestCase extends ApimBaseTest { - - private static final String SAMPLE_API_NAME = "APIKeyTestAPI"; - private static final String SAMPLE_API_CONTEXT = "apiKey"; - private static final String SAMPLE_API_VERSION = "1.0.0"; - private static final String APP_NAME = "APIKeyTestApp"; - private String apiKey; - private String apiKeyForIPTest; - private String apiKeyForRefererTest; - private String tamperedAPIKey; - private String applicationId; - private String apiId; - private String endPoint; - private String jwtEndpoint; - - @BeforeClass(description = "Initialise the setup for API key tests") - void start() throws Exception { - super.initWithSuperTenant(); - - String targetDir = Utils.getTargetDirPath(); - String filePath = targetDir + ApictlUtils.OPENAPIS_PATH + "api_key_openAPI.yaml"; - - // enable apikey in apim - JSONArray securityScheme = new JSONArray(); - securityScheme.put("oauth_basic_auth_api_key_mandatory"); - securityScheme.put("api_key"); - - JSONObject apiProperties = new JSONObject(); - apiProperties.put("name", SAMPLE_API_NAME); - apiProperties.put("context", "/" + SAMPLE_API_CONTEXT); - apiProperties.put("version", SAMPLE_API_VERSION); - apiProperties.put("provider", user.getUserName()); - apiProperties.put("securityScheme", securityScheme); - apiId = PublisherUtils.createAPIUsingOAS(apiProperties, filePath, publisherRestClient); - - publisherRestClient.changeAPILifeCycleStatus(apiId, "Publish"); - - // creating the application - Application app = new Application(APP_NAME, TestConstant.APPLICATION_TIER.UNLIMITED); - applicationId = StoreUtils.createApplication(app, storeRestClient); - - PublisherUtils.createAPIRevisionAndDeploy(apiId, publisherRestClient); - - StoreUtils.subscribeToAPI(apiId, applicationId, TestConstant.SUBSCRIPTION_TIER.UNLIMITED, storeRestClient); - - endPoint = Utils.getServiceURLHttps(SAMPLE_API_CONTEXT + "/1.0.0/pet/1"); - jwtEndpoint = Utils.getServiceURLHttps(SAMPLE_API_CONTEXT + "/1.0.0/jwtheader"); - - // Obtain API keys - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - apiKey = apiKeyDTO.getApikey(); - tamperedAPIKey = apiKey.substring(0, apiKey.length() - 400); - - APIKeyDTO ipTestAPIKeyDTO = storeRestClient.generateAPIKeys(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - -1, "192.168.1.1", null); - apiKeyForIPTest = ipTestAPIKeyDTO.getApikey(); - - APIKeyDTO refererTestAPIKeyDTO = storeRestClient.generateAPIKeys(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - -1, null, "http://www.abc.com"); - apiKeyForRefererTest = refererTestAPIKeyDTO.getApikey(); - - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); - } - - // Invokes with tampered API key and this will fail. - @Test(description = "Test to detect wrong API keys") - public void invokeWithTamperedAPIKey() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", tamperedAPIKey); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED, "Response code mismatched"); - Assert.assertTrue(response.getData().contains("Invalid Credentials"), "Error response message mismatch"); - } - - // When invoke with original token even though the tampered API key is in the invalid key cache, - // original token should pass. - @Test(description = "Test to check the API Key in header is working", dependsOnMethods = "invokeWithTamperedAPIKey") - public void invokeAPIKeyInHeaderSuccessTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKey); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - //Invoke API by including the API key as a query parameter - @Test(description = "Test to check the API Key in query param is working") - public void invokeAPIKeyInQueryParamSuccessTest() throws Exception { - Map headers = new HashMap<>(); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps(endPoint + "?apikey=" + apiKey), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - @Test(description = "Test to check the API key auth validate invalid signature key") - public void invokeAPIKeyHeaderInvalidTokenTest() throws Exception { - // Set header - Map headers = new HashMap<>(); - headers.put("apikey", TestConstant.INVALID_JWT_TOKEN); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED, "Response code mismatched"); - Assert.assertTrue(response.getData().contains("Invalid Credentials"), "Error response message mismatch"); - } - - // After invoking with original key, it is cached as a success token. But again using the tampered key should fail. - @Test(description = "Test to check the APIKey is working", dependsOnMethods = "invokeAPIKeyInHeaderSuccessTest") - public void invokeAgainWithTamperedAPIKey() throws Exception { - // Sets header - Map headers = new HashMap<>(); - headers.put("apikey", tamperedAPIKey); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_UNAUTHORIZED, "Response code mismatched"); - Assert.assertTrue(response.getData().contains("Invalid Credentials"), "Error response message mismatch"); - } - - // Ensures whether a given API key is expired or not - @Test(description = "Test to check the API key auth validate expired token") - public void invokeExpiredAPIKeyTest() throws Exception { - // Sets header - Map headers = new HashMap(); - headers.put("apikey", TestConstant.EXPIRED_API_KEY_TOKEN); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertTrue(response.getData().contains("Invalid Credentials"), "Error response message mismatch"); - } - - @Test(description = "Test to check the API Key for incorrect IP address is not working") - public void invokeAPIKeyForIncorrectIPAddressTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKeyForIPTest); - headers.put("permittedIP", "192.168.1.2"); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertTrue(response.getData().contains("Resource forbidden"), "Error response message mismatch"); - } - - - @Test(description = "Test to check the API Key for incorrect referer address is not working") - public void invokeAPIKeyForIncorrectRefererTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKeyForRefererTest); - headers.put("referer", "http://www.abcd.com"); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertTrue(response.getData().contains("Resource forbidden"), "Error response message mismatch"); - } - - @Test(description = "Test to check the API Key for specific IP address is working") - public void invokeAPIKeyForIPAddressSuccessTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKeyForIPTest); - headers.put("x-forwarded-for", "192.168.1.1"); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - @Test(description = "Test to check the API Key for specific referer address is working") - public void invokeAPIKeyForRefererSuccessTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKeyForRefererTest); - headers.put("referer", "http://www.abc.com"); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - } - - @Test(description = "Test to check the backend JWT generation for API Key") - public void apiKeyBackendJwtGenerationTestWithAPIM() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKey); - HttpResponse response = HttpClientRequest.doGet( - Utils.getServiceURLHttps("/apiKey/1.0.0/jwtheader"), headers); - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), HttpStatus.SC_OK, "Response code mismatched"); - Assert.assertEquals(response.getData(), ResponseConstants.VALID_JWT_RESPONSE, "Response body mismatched"); - } - - @AfterClass - public void clean() throws Exception { - StoreUtils.removeAllSubscriptionsForAnApp(applicationId, storeRestClient); - storeRestClient.removeApplicationById(applicationId); - publisherRestClient.deleteAPI(apiId); - } -} diff --git a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/InternalKeyHeaderTestCase.java b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/InternalKeyHeaderTestCase.java index c2ba55defc..4bcf7d76fb 100644 --- a/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/InternalKeyHeaderTestCase.java +++ b/integration/test-integration/src/test/java/org/wso2/choreo/connect/tests/testcases/withapim/apikey/InternalKeyHeaderTestCase.java @@ -41,8 +41,6 @@ public class InternalKeyHeaderTestCase extends ApimBaseTest { private static final String SAMPLE_API_CONTEXT = "apiKeyHeader"; private static final String SAMPLE_API_VERSION = "1.0.0"; private static final String APP_NAME = "APIKeyHeaderTestApp"; - - protected String apiKey; private String endPoint; private String internalKey; @@ -56,7 +54,6 @@ void start() throws Exception { // enable apikey in apim JSONArray securityScheme = new JSONArray(); securityScheme.put("oauth_basic_auth_api_key_mandatory"); - securityScheme.put("api_key"); JSONObject apiProperties = new JSONObject(); apiProperties.put("name", SAMPLE_API_NAME); @@ -83,26 +80,9 @@ void start() throws Exception { publisherRestClient.generateInternalApiKey(apiId); internalKey = internalApiKeyDTO.getData().getApikey(); - // Obtain API key - APIKeyDTO apiKeyDTO = StoreUtils.generateAPIKey(applicationId, TestConstant.KEY_TYPE_PRODUCTION, - storeRestClient); - apiKey = apiKeyDTO.getApikey(); - Utils.delay(TestConstant.DEPLOYMENT_WAIT_TIME, "Could not wait till initial setup completion."); } - @Test(description = "Test to check the API Key in header is working") - public void invokeAPIKeyWithSimilarHeaderSuccessTest() throws Exception { - Map headers = new HashMap<>(); - headers.put("apikey", apiKey); - HttpResponse response = HttpClientRequest.doGet(Utils.getServiceURLHttps(endPoint), headers); - - Assert.assertNotNull(response); - Assert.assertEquals(response.getResponseCode(), - com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus.SC_OK, - "Response code mismatched"); - } - @Test(description = "Test to check the Internal Key in header is working") public void invokeInternalAPIKeyWithSimilarHeaderSuccessTest() throws Exception { // Set header diff --git a/integration/test-integration/src/test/resources/testng-cc-standalone.xml b/integration/test-integration/src/test/resources/testng-cc-standalone.xml index c7e4d6ff8c..d7d667cda6 100644 --- a/integration/test-integration/src/test/resources/testng-cc-standalone.xml +++ b/integration/test-integration/src/test/resources/testng-cc-standalone.xml @@ -66,7 +66,6 @@ - diff --git a/integration/test-integration/src/test/resources/testng-cc-with-apim.xml b/integration/test-integration/src/test/resources/testng-cc-with-apim.xml index 5cb4f34c42..46afaf499f 100644 --- a/integration/test-integration/src/test/resources/testng-cc-with-apim.xml +++ b/integration/test-integration/src/test/resources/testng-cc-with-apim.xml @@ -59,10 +59,6 @@ - - - -