Implement api keymgt extension See merge request entgra/carbon-device-mgt!890merge-requests/884/merge
commit
b894d371fb
@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>apimgt-extensions</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<version>5.0.7-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>org.wso2.carbon.apimgt.keymgt.extension</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - API Key Management</name>
|
||||||
|
<description>This module extends the API manager's key management.</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec.wso2</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.apimgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.apimgt.keymgt</artifactId>
|
||||||
|
<version>${carbon.api.mgt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<version>1.4.0</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
|
||||||
|
<Bundle-Description>API Management Application Bundle</Bundle-Description>
|
||||||
|
<Import-Packages>
|
||||||
|
</Import-Packages>
|
||||||
|
<Export-Package>
|
||||||
|
org.wso2.carbon.apimgt.keymgt.extension
|
||||||
|
</Export-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>jacoco-initialize</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>jacoco-site</id>
|
||||||
|
<phase>test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
|
||||||
|
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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.carbon.apimgt.keymgt.extension;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.apimgt.api.APIManagementException;
|
||||||
|
import org.wso2.carbon.apimgt.api.model.AccessTokenInfo;
|
||||||
|
import org.wso2.carbon.apimgt.api.model.KeyManager;
|
||||||
|
import org.wso2.carbon.apimgt.api.model.subscription.URLMapping;
|
||||||
|
import org.wso2.carbon.apimgt.impl.APIConstants;
|
||||||
|
import org.wso2.carbon.apimgt.impl.caching.CacheProvider;
|
||||||
|
import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO;
|
||||||
|
import org.wso2.carbon.apimgt.impl.dto.KeyManagerDto;
|
||||||
|
import org.wso2.carbon.apimgt.impl.factory.KeyManagerHolder;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.APIKeyMgtException;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.SubscriptionDataHolder;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.handlers.DefaultKeyValidationHandler;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.model.SubscriptionDataStore;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.model.entity.API;
|
||||||
|
import org.wso2.carbon.apimgt.keymgt.service.TokenValidationContext;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.common.permission.mgt.Permission;
|
||||||
|
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException;
|
||||||
|
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService;
|
||||||
|
import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionManagerServiceImpl;
|
||||||
|
import org.wso2.carbon.user.api.UserRealm;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
public class KeyValidationHandler extends DefaultKeyValidationHandler {
|
||||||
|
|
||||||
|
/* This key validation handler is written extending API Manager's
|
||||||
|
* AbstractKeyValidationHandler, which implements KeyValidationHandler
|
||||||
|
* where all the methods have been implemented. Since the logic is
|
||||||
|
* taken from KeyValidationHandler, the latest logical changes
|
||||||
|
* should be monitored and updated here accordingly */
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(KeyValidationHandler.class);
|
||||||
|
|
||||||
|
public KeyValidationHandler() {
|
||||||
|
log.info(this.getClass().getName() + " Initialised");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateScopes(TokenValidationContext validationContext) throws APIKeyMgtException {
|
||||||
|
|
||||||
|
if (validationContext.isCacheHit()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
APIKeyValidationInfoDTO apiKeyValidationInfoDTO = validationContext.getValidationInfoDTO();
|
||||||
|
|
||||||
|
if (apiKeyValidationInfoDTO == null) {
|
||||||
|
throw new APIKeyMgtException("Key Validation information not set");
|
||||||
|
}
|
||||||
|
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||||
|
String httpVerb = validationContext.getHttpVerb();
|
||||||
|
String[] scopes;
|
||||||
|
Set<String> scopesSet = apiKeyValidationInfoDTO.getScopes();
|
||||||
|
StringBuilder scopeList = new StringBuilder();
|
||||||
|
|
||||||
|
if (scopesSet != null && !scopesSet.isEmpty()) {
|
||||||
|
scopes = scopesSet.toArray(new String[scopesSet.size()]);
|
||||||
|
if (log.isDebugEnabled() && scopes != null) {
|
||||||
|
for (String scope : scopes) {
|
||||||
|
scopeList.append(scope);
|
||||||
|
scopeList.append(",");
|
||||||
|
}
|
||||||
|
scopeList.deleteCharAt(scopeList.length() - 1);
|
||||||
|
log.debug("Scopes allowed for token : " + validationContext.getAccessToken() + " : "
|
||||||
|
+ scopeList.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String resourceList = validationContext.getMatchingResource();
|
||||||
|
List<String> resourceArray;
|
||||||
|
if ((APIConstants.GRAPHQL_QUERY.equalsIgnoreCase(validationContext.getHttpVerb()))
|
||||||
|
|| (APIConstants.GRAPHQL_MUTATION.equalsIgnoreCase(validationContext.getHttpVerb()))
|
||||||
|
|| (APIConstants.GRAPHQL_SUBSCRIPTION.equalsIgnoreCase(validationContext.getHttpVerb()))) {
|
||||||
|
resourceArray = new ArrayList<>(Arrays.asList(resourceList.split(",")));
|
||||||
|
} else {
|
||||||
|
resourceArray = new ArrayList<>(Arrays.asList(resourceList));
|
||||||
|
}
|
||||||
|
|
||||||
|
String actualVersion = validationContext.getVersion();
|
||||||
|
//Check if the api version has been prefixed with _default_
|
||||||
|
if (actualVersion != null && actualVersion.startsWith(APIConstants.DEFAULT_VERSION_PREFIX)) {
|
||||||
|
//Remove the prefix from the version.
|
||||||
|
actualVersion = actualVersion.split(APIConstants.DEFAULT_VERSION_PREFIX)[1];
|
||||||
|
}
|
||||||
|
SubscriptionDataStore tenantSubscriptionStore =
|
||||||
|
SubscriptionDataHolder.getInstance().getTenantSubscriptionStore(tenantDomain);
|
||||||
|
API api = tenantSubscriptionStore.getApiByContextAndVersion(validationContext.getContext(),
|
||||||
|
actualVersion);
|
||||||
|
boolean scopesValidated = false;
|
||||||
|
if (api != null) {
|
||||||
|
|
||||||
|
for (String resource : resourceArray) {
|
||||||
|
List<URLMapping> resources = api.getResources();
|
||||||
|
URLMapping urlMapping = null;
|
||||||
|
for (URLMapping mapping : resources) {
|
||||||
|
if (Objects.equals(mapping.getHttpMethod(), httpVerb) || "WS".equalsIgnoreCase(api.getApiType())) {
|
||||||
|
if (isResourcePathMatching(resource, mapping)) {
|
||||||
|
urlMapping = mapping;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (urlMapping != null) {
|
||||||
|
if (urlMapping.getScopes().size() == 0) {
|
||||||
|
scopesValidated = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<String> mappingScopes = urlMapping.getScopes();
|
||||||
|
boolean validate = false;
|
||||||
|
for (String scope : mappingScopes) {
|
||||||
|
if (scopesSet.contains(scope)) {
|
||||||
|
scopesValidated = true;
|
||||||
|
validate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
validate = scopesValidated = authorizePermissions(validationContext);
|
||||||
|
break;
|
||||||
|
} catch (UserStoreException e) {
|
||||||
|
String msg = "Error occurred while validating user permissions";
|
||||||
|
log.error(msg, e);
|
||||||
|
throw new APIKeyMgtException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!validate && urlMapping.getScopes().size() > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!scopesValidated) {
|
||||||
|
apiKeyValidationInfoDTO.setAuthorized(false);
|
||||||
|
apiKeyValidationInfoDTO.setValidationStatus(APIConstants.KeyValidationStatus.INVALID_SCOPE);
|
||||||
|
}
|
||||||
|
return scopesValidated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorizes the permissions of a user for a given context
|
||||||
|
*
|
||||||
|
* @param validationContext token validation context object
|
||||||
|
* @return returns whether a user is authorized
|
||||||
|
* @throws UserStoreException throws if an error occurs while getting the tenant user realm
|
||||||
|
* */
|
||||||
|
private boolean authorizePermissions(TokenValidationContext validationContext) throws UserStoreException {
|
||||||
|
PrivilegedCarbonContext context = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||||
|
String username;
|
||||||
|
|
||||||
|
RealmService realmService = (RealmService) context.getOSGiService(RealmService.class, null);
|
||||||
|
UserRealm userRealm = realmService.getTenantUserRealm(PrivilegedCarbonContext
|
||||||
|
.getThreadLocalCarbonContext().getTenantId());;
|
||||||
|
AccessTokenInfo accessTokenInfo;
|
||||||
|
try {
|
||||||
|
accessTokenInfo = getAccessTokenInfo(validationContext);
|
||||||
|
} catch (APIManagementException e) {
|
||||||
|
log.error("Error occurred while getting access token info");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
username = accessTokenInfo.getEndUserName();
|
||||||
|
String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username);
|
||||||
|
|
||||||
|
List<Permission> matchingPermissions;
|
||||||
|
StringBuilder ctx = new StringBuilder();
|
||||||
|
try {
|
||||||
|
PermissionManagerService permissionManagerService = PermissionManagerServiceImpl.getInstance();
|
||||||
|
String[] ctxArr = validationContext.getContext().split("/");
|
||||||
|
for (String c : ctxArr) {
|
||||||
|
if (c.matches("[v|V]\\d{1,3}\\.\\d{1,3}"))
|
||||||
|
ctx.append(c);
|
||||||
|
}
|
||||||
|
ctx = new StringBuilder(ctxArr[0] + "/" + ctxArr[1] + "/" + ctxArr[2] + "/" + ctxArr[3]);
|
||||||
|
matchingPermissions = permissionManagerService.getPermission(ctx.toString());
|
||||||
|
} catch (PermissionManagementException e) {
|
||||||
|
log.error("Error occurred while fetching permissions for context " + ctx, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String requestUri = validationContext.getContext();
|
||||||
|
String requestMethod = validationContext.getHttpVerb();
|
||||||
|
String contextPath = ctx.toString();
|
||||||
|
|
||||||
|
if (matchingPermissions == null) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Permission to request '" + requestUri + "' is not defined in the configuration");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String requiredPermission = null;
|
||||||
|
List<MatchingResource> matchingResources = new ArrayList<>();
|
||||||
|
for (Permission permission : matchingPermissions) {
|
||||||
|
if (requestMethod.equals(permission.getMethod()) && requestUri.matches(permission.getUrlPattern())) {
|
||||||
|
if (requestUri.equals(permission.getUrl())) { // is there a exact match
|
||||||
|
requiredPermission = permission.getPath();
|
||||||
|
break;
|
||||||
|
} else { // all templated urls add to a list
|
||||||
|
matchingResources.add(new MatchingResource(permission.getUrlPattern().replace(contextPath, ""), permission.getPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredPermission == null) {
|
||||||
|
if (matchingResources.size() == 1) { // only 1 templated url found
|
||||||
|
requiredPermission = matchingResources.get(0).getPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchingResources.size() > 1) { // more than 1 templated urls found
|
||||||
|
String urlWithoutContext = requestUri.replace(contextPath, "");
|
||||||
|
StringTokenizer st = new StringTokenizer(urlWithoutContext, "/");
|
||||||
|
int tokenPosition = 1;
|
||||||
|
while (st.hasMoreTokens()) {
|
||||||
|
List<MatchingResource> tempList = new ArrayList<>();
|
||||||
|
String currentToken = st.nextToken();
|
||||||
|
for (MatchingResource matchingResource : matchingResources) {
|
||||||
|
StringTokenizer stmr = new StringTokenizer(matchingResource.getUrlPattern(), "/");
|
||||||
|
int internalTokenPosition = 1;
|
||||||
|
while (stmr.hasMoreTokens()) {
|
||||||
|
String internalToken = stmr.nextToken();
|
||||||
|
if ((tokenPosition == internalTokenPosition) && currentToken.equals(internalToken)) {
|
||||||
|
tempList.add(matchingResource);
|
||||||
|
}
|
||||||
|
internalTokenPosition++;
|
||||||
|
if (tokenPosition < internalTokenPosition) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tempList.size() == 1) {
|
||||||
|
requiredPermission = tempList.get(0).getPermission();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tokenPosition++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredPermission == null) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Matching permission not found for " + requestUri);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isUserAuthorized;
|
||||||
|
try {
|
||||||
|
isUserAuthorized = userRealm.getAuthorizationManager().isUserAuthorized(
|
||||||
|
tenantAwareUsername,
|
||||||
|
requiredPermission,
|
||||||
|
"ui.execute" // check against null values
|
||||||
|
);
|
||||||
|
return isUserAuthorized;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error occurred while retrieving user store. " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessTokenInfo getAccessTokenInfo(TokenValidationContext validationContext)
|
||||||
|
throws APIManagementException {
|
||||||
|
|
||||||
|
Object cachedAccessTokenInfo =
|
||||||
|
CacheProvider.createIntrospectionCache().get(validationContext.getAccessToken());
|
||||||
|
if (cachedAccessTokenInfo != null) {
|
||||||
|
return (AccessTokenInfo) cachedAccessTokenInfo;
|
||||||
|
}
|
||||||
|
String electedKeyManager = null;
|
||||||
|
// Obtaining details about the token.
|
||||||
|
if (StringUtils.isNotEmpty(validationContext.getTenantDomain())) {
|
||||||
|
Map<String, KeyManagerDto>
|
||||||
|
tenantKeyManagers = KeyManagerHolder.getTenantKeyManagers(validationContext.getTenantDomain());
|
||||||
|
KeyManager keyManagerInstance = null;
|
||||||
|
if (tenantKeyManagers.values().size() == 1) {
|
||||||
|
Map.Entry<String, KeyManagerDto> entry = tenantKeyManagers.entrySet().iterator().next();
|
||||||
|
if (entry != null) {
|
||||||
|
KeyManagerDto keyManagerDto = entry.getValue();
|
||||||
|
if (keyManagerDto != null && (validationContext.getKeyManagers()
|
||||||
|
.contains(APIConstants.KeyManager.API_LEVEL_ALL_KEY_MANAGERS) ||
|
||||||
|
validationContext.getKeyManagers().contains(keyManagerDto.getName()))) {
|
||||||
|
keyManagerInstance = keyManagerDto.getKeyManager();
|
||||||
|
electedKeyManager = entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tenantKeyManagers.values().size() > 1) {
|
||||||
|
if (validationContext.getKeyManagers()
|
||||||
|
.contains(APIConstants.KeyManager.API_LEVEL_ALL_KEY_MANAGERS)) {
|
||||||
|
for (Map.Entry<String, KeyManagerDto> keyManagerDtoEntry : tenantKeyManagers.entrySet()) {
|
||||||
|
if (keyManagerDtoEntry.getValue().getKeyManager() != null &&
|
||||||
|
keyManagerDtoEntry.getValue().getKeyManager()
|
||||||
|
.canHandleToken(validationContext.getAccessToken())) {
|
||||||
|
keyManagerInstance = keyManagerDtoEntry.getValue().getKeyManager();
|
||||||
|
electedKeyManager = keyManagerDtoEntry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (String selectedKeyManager : validationContext.getKeyManagers()) {
|
||||||
|
KeyManagerDto keyManagerDto = tenantKeyManagers.get(selectedKeyManager);
|
||||||
|
if (keyManagerDto != null && keyManagerDto.getKeyManager() != null &&
|
||||||
|
keyManagerDto.getKeyManager().canHandleToken(validationContext.getAccessToken())) {
|
||||||
|
keyManagerInstance = keyManagerDto.getKeyManager();
|
||||||
|
electedKeyManager = selectedKeyManager;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyManagerInstance != null) {
|
||||||
|
AccessTokenInfo tokenInfo = keyManagerInstance.getTokenMetaData(validationContext.getAccessToken());
|
||||||
|
tokenInfo.setKeyManager(electedKeyManager);
|
||||||
|
CacheProvider.getGatewayIntrospectCache().put(validationContext.getAccessToken(), tokenInfo);
|
||||||
|
return tokenInfo;
|
||||||
|
} else {
|
||||||
|
log.debug("KeyManager not available to authorize token.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isResourcePathMatching(String resourceString, URLMapping urlMapping) {
|
||||||
|
|
||||||
|
String resource = resourceString.trim();
|
||||||
|
String urlPattern = urlMapping.getUrlPattern().trim();
|
||||||
|
|
||||||
|
if (resource.equalsIgnoreCase(urlPattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the urlPattern is only one character longer than the resource and the urlPattern ends with a '/'
|
||||||
|
if (resource.length() + 1 == urlPattern.length() && urlPattern.endsWith("/")) {
|
||||||
|
// Check if resource is equal to urlPattern if the trailing '/' of the urlPattern is ignored
|
||||||
|
String urlPatternWithoutSlash = urlPattern.substring(0, urlPattern.length() - 1);
|
||||||
|
return resource.equalsIgnoreCase(urlPatternWithoutSlash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.wso2.carbon.apimgt.keymgt.extension;
|
||||||
|
|
||||||
|
public class MatchingResource {
|
||||||
|
private String urlPattern;
|
||||||
|
private String permission;
|
||||||
|
|
||||||
|
public MatchingResource(String urlPattern, String permission) {
|
||||||
|
this.urlPattern = urlPattern;
|
||||||
|
this.permission = permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrlPattern() {
|
||||||
|
return urlPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrlPattern(String urlPattern) {
|
||||||
|
this.urlPattern = urlPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPermission() {
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermission(String permission) {
|
||||||
|
this.permission = permission;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2022, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ Entgra (Pvt) Ltd. 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>carbon-devicemgt</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<version>5.0.7-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>org.wso2.carbon.apimgt.keymgt.extension.feature</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>WSO2 Carbon - Api Key Mgt Extensions Feature</name>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
<description>This feature contains apimgt related key management extensions</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.apimgt.keymgt.extension</artifactId>
|
||||||
|
<version>${carbon.device.mgt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-resources</id>
|
||||||
|
<phase>generate-resources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>src/main/resources</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>resources</directory>
|
||||||
|
<includes>
|
||||||
|
<include>build.properties</include>
|
||||||
|
<include>p2.inf</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.wso2.maven</groupId>
|
||||||
|
<artifactId>carbon-p2-plugin</artifactId>
|
||||||
|
<version>${carbon.p2.plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>p2-feature-generation</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>p2-feature-gen</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<id>org.wso2.carbon.apimgt.keymgt.extension</id>
|
||||||
|
<propertiesFile>../../../features/etc/feature.properties</propertiesFile>
|
||||||
|
<adviceFile>
|
||||||
|
<properties>
|
||||||
|
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
|
||||||
|
<propertyDef>org.eclipse.equinox.p2.type.group:false</propertyDef>
|
||||||
|
</properties>
|
||||||
|
</adviceFile>
|
||||||
|
<bundles>
|
||||||
|
<bundleDef>
|
||||||
|
org.wso2.carbon.devicemgt:org.wso2.carbon.apimgt.keymgt.extension:${carbon.device.mgt.version}
|
||||||
|
</bundleDef>
|
||||||
|
</bundles>
|
||||||
|
<importBundles>
|
||||||
|
</importBundles>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1 @@
|
|||||||
|
custom = true
|
@ -0,0 +1 @@
|
|||||||
|
instructions.configure = \
|
Loading…
Reference in new issue