protected Cache getGatewayKeyCache() { String apimGWCacheExpiry = ServiceReferenceHolder.getInstance() .getAPIManagerConfiguration() .getFirstProperty(APIConstants.TOKEN_CACHE_EXPIRY); if (!gatewayKeyCacheInit) { gatewayKeyCacheInit = true; if (apimGWCacheExpiry != null) { return APIUtil.getCache( APIConstants.API_MANAGER_CACHE_MANAGER, APIConstants.GATEWAY_KEY_CACHE_NAME, Long.parseLong(apimGWCacheExpiry), Long.parseLong(apimGWCacheExpiry)); } else { long defaultCacheTimeout = Long.valueOf( ServerConfiguration.getInstance() .getFirstProperty(APIConstants.DEFAULT_CACHE_TIMEOUT)) * 60; return APIUtil.getCache( APIConstants.API_MANAGER_CACHE_MANAGER, APIConstants.GATEWAY_KEY_CACHE_NAME, defaultCacheTimeout, defaultCacheTimeout); } } return Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) .getCache(APIConstants.GATEWAY_KEY_CACHE_NAME); }
protected Cache getResourceCache() { if (!resourceCacheInit) { resourceCacheInit = true; long defaultCacheTimeout = Long.valueOf( ServerConfiguration.getInstance() .getFirstProperty(APIConstants.DEFAULT_CACHE_TIMEOUT)) * 60; return APIUtil.getCache( APIConstants.API_MANAGER_CACHE_MANAGER, APIConstants.RESOURCE_CACHE_NAME, defaultCacheTimeout, defaultCacheTimeout); } return Caching.getCacheManager(APIConstants.API_MANAGER_CACHE_MANAGER) .getCache(APIConstants.RESOURCE_CACHE_NAME); }
/** * Invalidates registry cache of the resource in the given path in given server * * @param path registry path of the resource * @param tenantDomain * @param serverURL * @param cookie * @throws AxisFault * @throws RemoteException * @throws APIManagementException */ public void clearCache(String path, String tenantDomain, String serverURL, String cookie) throws AxisFault, RemoteException, APIManagementException { RegistryCacheInvalidationServiceStub registryCacheServiceStub; ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null); registryCacheServiceStub = new RegistryCacheInvalidationServiceStub( ctx, serverURL + "RegistryCacheInvalidationService"); ServiceClient client = registryCacheServiceStub._getServiceClient(); Options options = client.getOptions(); options.setTimeOutInMilliSeconds(TIMEOUT_IN_MILLIS); options.setProperty(HTTPConstants.SO_TIMEOUT, TIMEOUT_IN_MILLIS); options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, TIMEOUT_IN_MILLIS); options.setManageSession(true); options.setProperty(HTTPConstants.COOKIE_STRING, cookie); try { registryCacheServiceStub.invalidateCache(path, tenantDomain); } catch (RegistryCacheInvalidationServiceAPIManagementExceptionException e) { APIUtil.handleException(e.getMessage(), e); } }
public void invalidateCache(String tenantDomain) { APIUtil.clearTiersCache(tenantDomain); }
public VerbInfoDTO findMatchingVerb(MessageContext synCtx) throws ResourceNotFoundException, APISecurityException { VerbInfoDTO verb = null; // This function is used by more than one handler. If on one execution of this function, it has // found and placed // the matching verb in the cache, the same can be re-used from all handlers since all handlers // share the same // MessageContext. The API_RESOURCE_CACHE_KEY property will be set in the MessageContext to // indicate that the // verb has been put into the cache. String resourceCacheKey = (String) synCtx.getProperty(APIConstants.API_RESOURCE_CACHE_KEY); if (resourceCacheKey != null) { verb = (VerbInfoDTO) getResourceCache().get(resourceCacheKey); // Cache hit if (verb != null) { if (log.isDebugEnabled()) { log.debug("Found resource in Cache for key: ".concat(resourceCacheKey)); } return verb; } if (log.isDebugEnabled()) { log.debug("Resource not found in cache for key: ".concat(resourceCacheKey)); } } String resourceString = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE); String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT); String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION); String fullRequestPath = (String) synCtx.getProperty(RESTConstants.REST_FULL_REQUEST_PATH); String apiName = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API); String requestPath = Utils.getRequestPath(synCtx, fullRequestPath, apiContext, apiVersion); if ("".equals(requestPath)) { requestPath = "/"; } if (log.isDebugEnabled()) { log.debug("Setting REST_SUB_REQUEST_PATH in msg context: ".concat(requestPath)); } synCtx.setProperty(RESTConstants.REST_SUB_REQUEST_PATH, requestPath); String httpMethod = (String) ((Axis2MessageContext) synCtx) .getAxis2MessageContext() .getProperty(Constants.Configuration.HTTP_METHOD); if (resourceString == null) { API selectedApi = synCtx.getConfiguration().getAPI(apiName); Resource selectedResource = null; if (selectedApi != null) { Resource[] selectedAPIResources = selectedApi.getResources(); Set<Resource> acceptableResources = new HashSet<Resource>(); for (Resource resource : selectedAPIResources) { // If the requesting method is OPTIONS or if the Resource contains the requesting method if (RESTConstants.METHOD_OPTIONS.equals(httpMethod) || (resource.getMethods() != null && Arrays.asList(resource.getMethods()).contains(httpMethod))) { acceptableResources.add(resource); } } if (acceptableResources.size() > 0) { for (RESTDispatcher dispatcher : RESTUtils.getDispatchers()) { Resource resource = dispatcher.findResource(synCtx, acceptableResources); if (resource != null && Arrays.asList(resource.getMethods()).contains(httpMethod)) { selectedResource = resource; break; } } } } if (selectedResource == null) { // No matching resource found. String msg = "Could not find matching resource for " + requestPath; log.error(msg); throw new ResourceNotFoundException(msg); } resourceString = selectedResource.getDispatcherHelper().getString(); resourceCacheKey = APIUtil.getResourceInfoDTOCacheKey(apiContext, apiVersion, resourceString, httpMethod); if (log.isDebugEnabled()) { log.debug("Selected Resource: ".concat(resourceString)); } // Set the elected resource synCtx.setProperty(APIConstants.API_ELECTED_RESOURCE, resourceString); } verb = (VerbInfoDTO) getResourceCache().get(resourceCacheKey); // Cache hit if (verb != null) { if (log.isDebugEnabled()) { log.debug("Got Resource from cache for key: ".concat(resourceCacheKey)); } // Set cache key in the message context so that it can be used by the subsequent handlers. synCtx.setProperty(APIConstants.API_RESOURCE_CACHE_KEY, resourceCacheKey); return verb; } if (log.isDebugEnabled()) { log.debug("Cache miss for Resource for key: ".concat(resourceCacheKey)); } String apiCacheKey = APIUtil.getAPIInfoDTOCacheKey(apiContext, apiVersion); APIInfoDTO apiInfoDTO = null; apiInfoDTO = (APIInfoDTO) getResourceCache().get(apiCacheKey); // Cache miss if (apiInfoDTO == null) { if (log.isDebugEnabled()) { log.debug("Could not find API object in cache for key: ".concat(apiCacheKey)); } apiInfoDTO = doGetAPIInfo(apiContext, apiVersion); getResourceCache().put(apiCacheKey, apiInfoDTO); } if (apiInfoDTO.getResources() != null) { for (ResourceInfoDTO resourceInfoDTO : apiInfoDTO.getResources()) { if ((resourceString.trim()).equalsIgnoreCase(resourceInfoDTO.getUrlPattern().trim())) { for (VerbInfoDTO verbDTO : resourceInfoDTO.getHttpVerbs()) { if (verbDTO.getHttpVerb().equals(httpMethod)) { if (log.isDebugEnabled()) { log.debug("Putting resource object in cache with key: ".concat(resourceCacheKey)); } verbDTO.setRequestKey(resourceCacheKey); // Store verb in cache getResourceCache().put(resourceCacheKey, verbDTO); // Set cache key in the message context so that it can be used by the subsequent // handlers. synCtx.setProperty(APIConstants.API_RESOURCE_CACHE_KEY, resourceCacheKey); return verbDTO; } } } } } return null; }
/** * Get the API key validated against the specified API * * @param context API context * @param apiKey API key to be validated * @param apiVersion API version number * @return An APIKeyValidationInfoDTO object * @throws APISecurityException If an error occurs while accessing backend services */ public APIKeyValidationInfoDTO getKeyValidationInfo( String context, String apiKey, String apiVersion, String authenticationScheme, String clientDomain, String matchingResource, String httpVerb, boolean defaultVersionInvoked) throws APISecurityException { String prefixedVersion = apiVersion; // Check if client has invoked the default version API. if (defaultVersionInvoked) { // Prefix the version so that it looks like _default_1.0 (_default_<version>)). // This is so that the Key Validator knows that this request is coming through a default api // version prefixedVersion = APIConstants.DEFAULT_VERSION_PREFIX.concat(prefixedVersion); } String cacheKey = APIUtil.getAccessTokenCacheKey( apiKey, context, prefixedVersion, matchingResource, httpVerb, authenticationScheme); // If Gateway key caching is enabled. if (gatewayKeyCacheEnabled) { // Get the access token from the first level cache. String cachedToken = (String) getGatewayTokenCache().get(apiKey); // If the access token exists in the first level cache. if (cachedToken != null) { APIKeyValidationInfoDTO info = (APIKeyValidationInfoDTO) getGatewayKeyCache().get(cacheKey); if (info != null) { if (APIUtil.isAccessTokenExpired(info)) { log.info("Invalid OAuth Token : Access Token " + apiKey + " expired."); info.setAuthorized(false); // in cache, if token is expired remove cache entry. getGatewayKeyCache().remove(cacheKey); // Remove from the first level token cache as well. getGatewayTokenCache().remove(apiKey); } return info; } } } // synchronized (apiKey.intern()) { // We synchronize on the API key here to allow concurrent processing // of different API keys - However when a burst of requests with the // same key is encountered, only one will be allowed to execute the logic, // and the rest will pick the value from the cache. // info = (APIKeyValidationInfoDTO) infoCache.get(cacheKey); // if (info != null) { // return info; // } APIKeyValidationInfoDTO info = doGetKeyValidationInfo( context, prefixedVersion, apiKey, authenticationScheme, clientDomain, matchingResource, httpVerb); if (info != null) { if (gatewayKeyCacheEnabled) { // Get the tenant domain of the API that is being invoked. String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); // Add to first level Token Cache. getGatewayTokenCache().put(apiKey, tenantDomain); // Add to Key Cache. getGatewayKeyCache().put(cacheKey, info); // If this is NOT a super-tenant API that is being invoked if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { // Add the tenant domain as a reference to the super tenant cache so we know from which // tenant cache // to remove the entry when the need occurs to clear this particular cache entry. try { PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext() .setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true); getGatewayTokenCache().put(apiKey, tenantDomain); } finally { PrivilegedCarbonContext.endTenantFlow(); } } } return info; } else { String warnMsg = "API key validation service returns null object"; log.warn(warnMsg); throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, warnMsg); } }
public void invoke(Request request, Response response, CompositeValve compositeValve) { if (authenticator == null) { authenticator = new APITokenAuthenticator(); } String context = request.getContextPath(); if (context == null || context.equals("")) { // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); return; } // todo remove version from context - special case for apps // context = stripVersionfromContext(context); boolean contextExist; Boolean contextValueInCache = null; if (APIUtil.getAPIContextCache().get(context) != null) { contextValueInCache = Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString()); } if (contextValueInCache != null) { contextExist = contextValueInCache; } else { contextExist = ApiMgtDAO.isContextExist(context); APIUtil.getAPIContextCache().put(context, contextExist); } if (!contextExist) { getNext().invoke(request, response, compositeValve); return; } handleWSDLGetRequest(request, response, compositeValve, context); String dispatcherPath = null; boolean forwardingRequired = false; long requestTime = System.currentTimeMillis(); APIManagerInterceptorOps interceptorOps = new APIManagerInterceptorOps(); UsageStatConfiguration statConfiguration = new UsageStatConfiguration(); if (contextExist) { // Use embedded API Management if (log.isDebugEnabled()) { log.debug("API Manager Interceptor Valve Got invoked!!"); } String bearerToken = request.getHeader(APIConstants.OperationParameter.AUTH_PARAM_NAME); String accessToken = null; /* Authenticate*/ try { if (bearerToken != null) { accessToken = APIManagetInterceptorUtils.getBearerToken(bearerToken); } else { // There can be some API published with None Auth Type /* * throw new * APIFaultException(APIConstants.KeyValidationStatus * .API_AUTH_INVALID_CREDENTIALS, * "Invalid format for Authorization header. Expected 'Bearer <token>'" * ); */ } String apiVersion = APIManagetInterceptorUtils.getAPIVersion(request); dispatcherPath = apiVersion; // todo get proper version // handling version for web-application API mgmt if (!APIManagerInterceptorConstant.DEFAULT_API_VERSION.equals(apiVersion) || "".equals(apiVersion)) { apiVersion = APIManagerInterceptorConstant.DEFAULT_API_VERSION; } else { forwardingRequired = true; } String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader()); String authLevel = authenticator.getResourceAuthenticationScheme( context, apiVersion, request.getRequestURI(), request.getMethod()); if (authLevel.equals(APIConstants.NO_MATCHING_AUTH_SCHEME)) { APIManagetInterceptorUtils.handleNoMatchAuthSchemeCallForRestService( response, request.getMethod(), request.getRequestURI(), apiVersion, context); return; } else { interceptorOps.doAuthenticate( context, APIConstants.DEFAULT_VERSION_PREFIX + apiVersion, accessToken, authLevel, domain); } } catch (APIManagementException e) { // ignore } catch (APIFaultException e) { /* If !isAuthorized APIFaultException is thrown*/ APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_SECURITY_NS, APIManagerErrorConstants.API_SECURITY_NS_PREFIX, response); return; } /* Throttle*/ try { interceptorOps.doThrottle(request, accessToken); } catch (APIFaultException e) { APIManagetInterceptorUtils.handleAPIFaultForRestService( e, APIManagerErrorConstants.API_THROTTLE_NS, APIManagerErrorConstants.API_THROTTLE_NS_PREFIX, response); return; } /* Publish Statistic if enabled*/ if (statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, false); } catch (APIManagementException e) { log.error("Error occurred when publishing stats", e); } } } if (forwardingRequired) { try { request .getRequestDispatcher( request.getContextPath() + "/services/customers/customerservice/customers/123") .forward(request, response); // response.sendRedirect(request.getContextPath() + // "/services/customers/customerservice/customers/123"); // return; } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // Invoke next valve in pipe. getNext().invoke(request, response, compositeValve); // Handle Responses if (contextExist && statConfiguration.isStatsPublishingEnabled()) { try { interceptorOps.publishStatistics(request, requestTime, true); } catch (APIManagementException e) { log.error("Error occurred when publishing stats", e); } } }
/** * This method updates the stat publishing status in gateway domain * * @param receiverUrl event receiver url * @param user username for the event receiver * @param password password for the event receiver * @param statUpdateStatus status of the stat publishing state * @throws APIManagementException if an error occurs while adding BAMServerProfile * @throws ClusteringFault if it fails to send cluster message to Gateway domain and update stats * publishing status * @throws Exception if an error occurs while updating EventingConfiguration */ public void updateStatPublishGateway( String receiverUrl, String user, String password, Boolean statUpdateStatus) throws APIManagementException, ClusteringFault, Exception { if (log.isDebugEnabled()) { log.debug("Updating stats publishing status in Gateway."); } // updating stat publishing at the receiver node, self update APIManagerAnalyticsConfiguration analyticsConfiguration = APIManagerAnalyticsConfiguration.getInstance(); analyticsConfiguration.setAnalyticsEnabled(statUpdateStatus); if (log.isDebugEnabled()) { log.debug("Updated stats publishing status in Gateway to : " + statUpdateStatus); } ServiceDataPublisherAdmin serviceDataPublisherAdmin = APIManagerComponent.getDataPublisherAdminService(); EventingConfigData eventingConfigData = null; if (serviceDataPublisherAdmin != null) { eventingConfigData = serviceDataPublisherAdmin.getEventingConfigData(); } if (eventingConfigData != null) { // config values must be updated if the stats publishing is true if (statUpdateStatus) { if (log.isDebugEnabled()) { log.debug("Updating values related to stats publishing status."); } // values related to stats publishing status are only updated if all of them are non-empty if (!(receiverUrl.isEmpty()) && !(user.isEmpty()) && !(password.isEmpty())) { analyticsConfiguration.setBamServerUrlGroups(receiverUrl); analyticsConfiguration.setBamServerUser(user); analyticsConfiguration.setBamServerPassword(password); eventingConfigData.setUrl(receiverUrl); eventingConfigData.setUserName(user); eventingConfigData.setPassword(password); if (log.isDebugEnabled()) { log.debug( "BAMServerURL : " + receiverUrl + " , BAMServerUserName : "******" , " + "BAMServerPassword : "******"Sending cluster message to Gateway domain to update stats publishing status."); } clusteringAgent.sendMessage( new StatUpdateClusterMessage(statUpdateStatus, receiverUrl, user, password), true); } }