Merge branch 'fix/cross-tenant-api-subscription' into 'master'

Fix cross-tenant api subscription issue

See merge request entgra/carbon-device-mgt!905
feature/traccar-sync
Pahansith Gunathilake 2 years ago
commit 2a5630cfb7

@ -87,12 +87,11 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi
@POST
public Response register(RegistrationProfile registrationProfile) {
try {
if (registrationProfile.getTags() == null || registrationProfile.getTags().length == 0) {
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("Tags should not be empty").build();
}
if (!APIUtil.getAllowedApisTags().containsAll(Arrays.asList(registrationProfile.getTags()))) {
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("APIs(Tags) are not allowed to this user."
).build();
if ((registrationProfile.getTags() != null && registrationProfile.getTags().length != 0)) {
if (!APIUtil.getAllowedApisTags().containsAll(Arrays.asList(registrationProfile.getTags()))) {
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("APIs(Tags) are not allowed to this user."
).build();
}
}
String username = APIUtil.getAuthenticatedUser();
@ -142,4 +141,4 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi
}
}
}
}

@ -0,0 +1,60 @@
<?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.11-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.keymgt.extension.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - API Key Management API</name>
<description>This module extends the API manager's key management apis.</description>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*cxf*.jar</packagingExcludes>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt.extension</artifactId>
<version>${carbon.device.mgt.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,90 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.api;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@JsonIgnoreProperties(ignoreUnknown = true)
public class DCRRequest {
@XmlElement(required = true)
private String clientName;
@XmlElement(required = true)
private String owner;
@XmlElement(required = true)
private String grantTypes;
@XmlElement
private String callBackUrl;
@XmlElement(required = true)
private String[] tags;
@XmlElement
private boolean isSaasApp;
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantTypes() {
return grantTypes;
}
public void setGrantTypes(String grantTypes) {
this.grantTypes = grantTypes;
}
public String getCallBackUrl() {
return callBackUrl;
}
public void setCallBackUrl(String callBackUrl) {
this.callBackUrl = callBackUrl;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public boolean getIsSaasApp() {
return isSaasApp;
}
public void setIsSaasApp(boolean saasApp) {
isSaasApp = saasApp;
}
}

@ -0,0 +1,46 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public interface KeyManagerService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/dynamic-client-registration")
Response dynamicClientRegistration(DCRRequest request);
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/token")
Response generateAccessToken(@FormParam("client_id") String clientId,
@FormParam("client_secret") String clientSecret,
@FormParam("refresh_token") String refreshToken,
@FormParam("scope") String scope,
@FormParam("grant_type") String grantType);
}

@ -0,0 +1,77 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.api;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.keymgt.extension.DCRResponse;
import org.wso2.carbon.apimgt.keymgt.extension.TokenRequest;
import org.wso2.carbon.apimgt.keymgt.extension.TokenResponse;
import org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtService;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtServiceImpl;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class KeyManagerServiceImpl implements KeyManagerService {
@Override
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/dynamic-client-registration")
public Response dynamicClientRegistration(DCRRequest dcrRequest) {
try {
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
DCRResponse resp = keyMgtService.dynamicClientRegistration(dcrRequest.getClientName(), dcrRequest.getOwner(),
dcrRequest.getGrantTypes(), dcrRequest.getCallBackUrl(), dcrRequest.getTags(), dcrRequest.getIsSaasApp());
return Response.status(Response.Status.CREATED).entity(resp).build();
} catch (KeyMgtException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/token")
public Response generateAccessToken(@FormParam("client_id") String clientId,
@FormParam("client_secret") String clientSecret,
@FormParam("refresh_token") String refreshToken,
@FormParam("scope") String scope,
@FormParam("grant_type") String grantType) {
try {
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
TokenResponse resp = keyMgtService.generateAccessToken(
new TokenRequest(clientId, clientSecret, refreshToken, scope, grantType));
return Response.status(Response.Status.CREATED).entity(resp).build();
} catch (KeyMgtException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
}
}
}

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019, 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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
For ex:
Actual API endpoint: devicemgt_admin/1.0.0/devices/{device-id}
URL to be represented here: /devices/*
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
</PermissionConfiguration>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF3,Carbon</Environments>
</Classloading>

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<jaxrs:server id="services" address="/">
<jaxrs:serviceBeans>
<ref bean="keyManagerService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="keyManagerService" class="org.wso2.carbon.apimgt.keymgt.extension.api.KeyManagerServiceImpl"/>
</beans>

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2021, Entgra (Pvt) Ltd. (http://www.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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Grafana-API-Proxy-Webapp</display-name>
<servlet>
<description>JAX-WS/JAX-RS Grafana API Management Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<!-- configure a security filter -->
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>ApiAuthorizationFilterImpl</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>basicAuth</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>
/keymgt-test-api/.*,
</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -43,7 +43,7 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.0</version>
<version>5.1.7</version>
<extensions>true</extensions>
<configuration>
<instructions>
@ -51,10 +51,16 @@
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Bundle-Version>${carbon.device.mgt.version}</Bundle-Version>
<Bundle-Description>API Management Application Bundle</Bundle-Description>
<Private-Package>org.wso2.carbon.apimgt.keymgt.extension.internal</Private-Package>
<Import-Packages>
org.wso2.carbon.apimgt.application.extension,
org.wso2.carbon.apimgt.application.extension.*,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.device.mgt.core.*
</Import-Packages>
<Export-Package>
org.wso2.carbon.apimgt.keymgt.extension
!org.wso2.carbon.apimgt.keymgt.extension.internal,
org.wso2.carbon.apimgt.keymgt.extension.*
</Export-Package>
</instructions>
</configuration>

@ -0,0 +1,49 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
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.impl.AMDefaultKeyManagerImpl;
public class CustomKeyManager extends AMDefaultKeyManagerImpl {
private static final Log log = LogFactory.getLog(CustomKeyManager.class);
/**
* This is used to get the metadata of the access token.
*
* @param accessToken AccessToken.
* @return The meta data details of access token.
* @throws APIManagementException This is the custom exception class for API management.
*/
@Override
public AccessTokenInfo getTokenMetaData(String accessToken) throws APIManagementException {
log.debug("Access Token With Prefix : "+accessToken);
String accessTokenWithoutPrefix = accessToken.substring(accessToken.indexOf("_")+1);
log.debug("Access Token WithOut Prefix : "+accessTokenWithoutPrefix);
return super.getTokenMetaData(accessTokenWithoutPrefix);
}
@Override
public String getType() {
return KeyMgtConstants.CUSTOM_TYPE;
}
}

@ -0,0 +1,45 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class DCRResponse {
String clientId;
String clientSecret;
public DCRResponse(String clientId, String clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
import org.wso2.carbon.apimgt.api.model.ConfigurationDto;
import org.wso2.carbon.apimgt.impl.APIConstants;
import org.wso2.carbon.apimgt.impl.DefaultKeyManagerConnectorConfiguration;
import org.wso2.carbon.apimgt.impl.jwt.JWTValidatorImpl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @scr.component name="org.wso2.carbon.apimgt.keymgt.extension.customKeyManagerConfigComponent" immediate="true"
*/
public class KeyManagerConnectorConfiguration extends DefaultKeyManagerConnectorConfiguration {
@Override
public String getImplementation() {
return CustomKeyManager.class.getName();
}
@Override
public String getJWTValidator() {
return JWTValidatorImpl.class.getName();
}
@Override
public List<ConfigurationDto> getApplicationConfigurations() {
return super.getApplicationConfigurations();
}
@Override
public String getType() {
return KeyMgtConstants.CUSTOM_TYPE;
}
@Override
public String getDefaultScopesClaim() {
return APIConstants.JwtTokenConstants.SCOPE;
}
@Override
public String getDefaultConsumerKeyClaim() {
return APIConstants.JwtTokenConstants.AUTHORIZED_PARTY;
}
@Override
public List<ConfigurationDto> getConnectionConfigurations() {
List<ConfigurationDto> configurationDtoList = new ArrayList<>();
configurationDtoList.add(new ConfigurationDto("Username", "Username", "input", "Username of admin user", "", true, false, Collections.emptyList(), false));
configurationDtoList.add(new ConfigurationDto("Password", "Password", "input", "Password of Admin user", "", true, true, Collections.emptyList(), false));
configurationDtoList.addAll(super.getConnectionConfigurations());
return configurationDtoList;
}
}

@ -0,0 +1,333 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class KeyManagerPayload {
private String name;
private String displayName;
private String type;
private String description;
private String wellKnownEndpoint;
private String introspectionEndpoint;
private String clientRegistrationEndpoint;
private String tokenEndpoint;
private String displayTokenEndpoint;
private String revokeEndpoint;
private String displayRevokeEndpoint;
private String userInfoEndpoint;
private String authorizeEndpoint;
private Map<String, String> certificates;
private String issuer;
private String scopeManagementEndpoint;
private List<String> availableGrantTypes;
private boolean enableTokenGeneration;
private boolean enableTokenEncryption;
private boolean enableTokenHashing;
private boolean enableMapOAuthConsumerApps;
private boolean enableOAuthAppCreation;
private boolean enableSelfValidationJWT;
private List<String> claimMapping;
private String consumerKeyClaim;
private String scopesClaim;
private List<Map<String, String>> tokenValidation;
private boolean enabled;
private Map<String, Object> additionalProperties;
public KeyManagerPayload(String domainName, int tenantId, String serverUrl, String name,
List<String> availableGrantTypes, Map<String, Object> additionalProperties) {
this.name = name;
this.displayName = name;
this.type = KeyMgtConstants.CUSTOM_TYPE;
this.description = "Custom Key Manager";
this.wellKnownEndpoint = null;
this.introspectionEndpoint = serverUrl + KeyMgtConstants.INTROSPECT_ENDPOINT;
this.clientRegistrationEndpoint = serverUrl + "/t/" + domainName + KeyMgtConstants.CLIENT_REGISTRATION_ENDPOINT;
this.tokenEndpoint = serverUrl + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
this.displayTokenEndpoint = serverUrl + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
this.revokeEndpoint = serverUrl + KeyMgtConstants.REVOKE_ENDPOINT;
this.displayRevokeEndpoint = serverUrl + KeyMgtConstants.REVOKE_ENDPOINT;
this.userInfoEndpoint = serverUrl + KeyMgtConstants.USER_INFO_ENDPOINT;
this.authorizeEndpoint = serverUrl + KeyMgtConstants.AUTHORIZE_ENDPOINT;
Map<String, String> certificates = new HashMap<>();
certificates.put("type", "JWKS");
certificates.put("value", serverUrl + "/t/" + domainName + KeyMgtConstants.JWKS_ENDPOINT);
this.certificates = certificates;
this.issuer = serverUrl + "/t/" + domainName + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
this.scopeManagementEndpoint = serverUrl + "/t/" + domainName + KeyMgtConstants.SCOPE_MANAGEMENT_ENDPOINT;
this.availableGrantTypes = availableGrantTypes;
this.enableTokenGeneration = true;
this.enableTokenEncryption = false;
this.enableTokenHashing = false;
this.enableMapOAuthConsumerApps = true;
this.enableOAuthAppCreation = true;
this.enableSelfValidationJWT = true;
this.claimMapping = new ArrayList<>();
this.consumerKeyClaim = KeyMgtConstants.CONSUMER_KEY_CLAIM;
this.scopesClaim = KeyMgtConstants.SCOPE_CLAIM;
List<Map<String, String>> tokenValidationList = new ArrayList<>();
Map<String, String> tokenValidation = new HashMap<>();
tokenValidation.put("type", KeyMgtConstants.REFERENCE);
tokenValidation.put("value", KeyMgtConstants.TOKEN_REGEX.replaceAll("<<tenantId>>", String.valueOf(tenantId)));
tokenValidationList.add(tokenValidation);
this.tokenValidation = tokenValidationList;
this.enabled = true;
this.additionalProperties = additionalProperties;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getWellKnownEndpoint() {
return wellKnownEndpoint;
}
public void setWellKnownEndpoint(String wellKnownEndpoint) {
this.wellKnownEndpoint = wellKnownEndpoint;
}
public String getIntrospectionEndpoint() {
return introspectionEndpoint;
}
public void setIntrospectionEndpoint(String introspectionEndpoint) {
this.introspectionEndpoint = introspectionEndpoint;
}
public String getClientRegistrationEndpoint() {
return clientRegistrationEndpoint;
}
public void setClientRegistrationEndpoint(String clientRegistrationEndpoint) {
this.clientRegistrationEndpoint = clientRegistrationEndpoint;
}
public String getTokenEndpoint() {
return tokenEndpoint;
}
public void setTokenEndpoint(String tokenEndpoint) {
this.tokenEndpoint = tokenEndpoint;
}
public String getDisplayTokenEndpoint() {
return displayTokenEndpoint;
}
public void setDisplayTokenEndpoint(String displayTokenEndpoint) {
this.displayTokenEndpoint = displayTokenEndpoint;
}
public String getRevokeEndpoint() {
return revokeEndpoint;
}
public void setRevokeEndpoint(String revokeEndpoint) {
this.revokeEndpoint = revokeEndpoint;
}
public String getDisplayRevokeEndpoint() {
return displayRevokeEndpoint;
}
public void setDisplayRevokeEndpoint(String displayRevokeEndpoint) {
this.displayRevokeEndpoint = displayRevokeEndpoint;
}
public String getUserInfoEndpoint() {
return userInfoEndpoint;
}
public void setUserInfoEndpoint(String userInfoEndpoint) {
this.userInfoEndpoint = userInfoEndpoint;
}
public String getAuthorizeEndpoint() {
return authorizeEndpoint;
}
public void setAuthorizeEndpoint(String authorizeEndpoint) {
this.authorizeEndpoint = authorizeEndpoint;
}
public Map<String, String> getCertificates() {
return certificates;
}
public void setCertificates(Map<String, String> certificates) {
this.certificates = certificates;
}
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getScopeManagementEndpoint() {
return scopeManagementEndpoint;
}
public void setScopeManagementEndpoint(String scopeManagementEndpoint) {
this.scopeManagementEndpoint = scopeManagementEndpoint;
}
public List<String> getAvailableGrantTypes() {
return availableGrantTypes;
}
public void setAvailableGrantTypes(List<String> availableGrantTypes) {
this.availableGrantTypes = availableGrantTypes;
}
public boolean isEnableTokenGeneration() {
return enableTokenGeneration;
}
public void setEnableTokenGeneration(boolean enableTokenGeneration) {
this.enableTokenGeneration = enableTokenGeneration;
}
public boolean isEnableTokenEncryption() {
return enableTokenEncryption;
}
public void setEnableTokenEncryption(boolean enableTokenEncryption) {
this.enableTokenEncryption = enableTokenEncryption;
}
public boolean isEnableTokenHashing() {
return enableTokenHashing;
}
public void setEnableTokenHashing(boolean enableTokenHashing) {
this.enableTokenHashing = enableTokenHashing;
}
public boolean isEnableMapOAuthConsumerApps() {
return enableMapOAuthConsumerApps;
}
public void setEnableMapOAuthConsumerApps(boolean enableMapOAuthConsumerApps) {
this.enableMapOAuthConsumerApps = enableMapOAuthConsumerApps;
}
public boolean isEnableOAuthAppCreation() {
return enableOAuthAppCreation;
}
public void setEnableOAuthAppCreation(boolean enableOAuthAppCreation) {
this.enableOAuthAppCreation = enableOAuthAppCreation;
}
public boolean isEnableSelfValidationJWT() {
return enableSelfValidationJWT;
}
public void setEnableSelfValidationJWT(boolean enableSelfValidationJWT) {
this.enableSelfValidationJWT = enableSelfValidationJWT;
}
public List<String> getClaimMapping() {
return claimMapping;
}
public void setClaimMapping(List<String> claimMapping) {
this.claimMapping = claimMapping;
}
public String getConsumerKeyClaim() {
return consumerKeyClaim;
}
public void setConsumerKeyClaim(String consumerKeyClaim) {
this.consumerKeyClaim = consumerKeyClaim;
}
public String getScopesClaim() {
return scopesClaim;
}
public void setScopesClaim(String scopesClaim) {
this.scopesClaim = scopesClaim;
}
public List<Map<String, String>> getTokenValidation() {
return tokenValidation;
}
public void setTokenValidation(List<Map<String, String>> tokenValidation) {
this.tokenValidation = tokenValidation;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Map<String, Object> getAdditionalProperties() {
return additionalProperties;
}
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
this.additionalProperties = additionalProperties;
}
}

@ -0,0 +1,52 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class KeyMgtConstants {
public static final String CUSTOM_TYPE = "CustomKeyManager";
public static final String RESERVED_OAUTH_APP_NAME_PREFIX = "reserved_app_for_";
public static final String SUPER_TENANT = "carbon.super";
public static final String DEFAULT_ADMIN_SCOPES =
"openid apim:admin apim:admin_operations apim:subscribe apim:app_manage apim:sub_manage";
public static final String CLIENT_CREDENTIALS_GRANT_TYPE = "client_credentials";
public static final String CONSUMER_KEY_CLAIM = "azp";
public static final String SCOPE_CLAIM = "scope";
public static final String REFERENCE = "REFERENCE";
public static final String TOKEN_REGEX =
"^<<tenantId>>*_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}";
public static final int TOKEN_VALIDITY_PERIOD = 3600;
public static final String CUSTOM_KEY_MANAGER_NAME_PREFIX = "KM_";
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String X_WSO2_TENANT_HEADER = "X-WSO2-Tenant";
public static final String OAUTH2_TOKEN_ENDPOINT = "/oauth2/token";
public static final String DCR_ENDPOINT = "/api-application-registration/register";
public static final String INTROSPECT_ENDPOINT = "/oauth2/introspect";
public static final String CLIENT_REGISTRATION_ENDPOINT = "/keymanager-operations/dcr/register";
public static final String REVOKE_ENDPOINT = "";
public static final String USER_INFO_ENDPOINT = "/oauth2/userInfo";
public static final String AUTHORIZE_ENDPOINT = "/oauth2/authorize";
public static final String SCOPE_MANAGEMENT_ENDPOINT = "/api/identity/oauth2/v1.0/scopes";
public static final String JWKS_ENDPOINT = "/oauth2/jwks";
public static final String CREATE_KEY_MANAGER_ENDPOINT = "/api/am/admin/v2/key-managers";
public static final String APPLICATION_KEY_MAPPING_ENDPOINT =
"/api/am/devportal/v2/applications/<applicationId>/map-keys";
public static final String APPLICATION_TOKEN_ENDPOINT =
"/api/am/devportal/v2/applications/<applicationId>/oauth-keys/<keyMappingId>/generate-token";
}

@ -1,3 +1,21 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class MatchingResource {

@ -0,0 +1,63 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class OAuthApplication {
private String clientName;
private String callBackUrl;
private String client_id;
private String client_secret;
public OAuthApplication(String client_id, String client_secret) {
this.client_id = client_id;
this.client_secret = client_secret;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getClientId() {
return client_id;
}
public void setClientId(String clientId) {
this.client_id = clientId;
}
public String getClientSecret() {
return client_secret;
}
public void setClientSecret(String clientSecret) {
this.client_secret = clientSecret;
}
public String getCallBackUrl() {
return callBackUrl;
}
public void setCallBackUrl(String callBackUrl) {
this.callBackUrl = callBackUrl;
}
}

@ -0,0 +1,75 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class TokenRequest {
private String clientId;
private String clientSecret;
private String refreshToken;
private String scope;
private String grantType;
public TokenRequest(String clientId, String clientSecret, String refreshToken, String scope, String grantType) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.refreshToken = refreshToken;
this.scope = scope;
this.grantType = grantType;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}

@ -0,0 +1,75 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension;
public class TokenResponse {
private String access_token;
private String refresh_token;
private String scope;
private String tokenType;
private int expires_in;
public TokenResponse(String access_token, String refresh_token, String scope, String tokenType, int expires_in) {
this.access_token = access_token;
this.refresh_token = refresh_token;
this.scope = scope;
this.tokenType = tokenType;
this.expires_in = expires_in;
}
public String getAccessToken() {
return access_token;
}
public void setAccessToken(String access_token) {
this.access_token = access_token;
}
public String getRefreshToken() {
return refresh_token;
}
public void setRefreshToken(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public int getExpiresIn() {
return expires_in;
}
public void setExpiresIn(int expires_in) {
this.expires_in = expires_in;
}
}

@ -0,0 +1,34 @@
/*
*
* * Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*
*
*/
/**
* Custom exception class for handling bad request exceptions.
*/
package org.wso2.carbon.apimgt.keymgt.extension.exception;
public class BadRequestException extends Exception {
private static final long serialVersionUID = -2387103750774855056L;
public BadRequestException(String errorMessage) {
super(errorMessage);
}
}

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.exception;
/**
* Custom exception class for key management service related exceptions.
*/
public class KeyMgtException extends Exception {
private static final long serialVersionUID = -3806174803586013552L;
public KeyMgtException(String errorMessage) {
super(errorMessage);
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.internal;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtService;
public class KeyMgtDataHolder {
private static final KeyMgtDataHolder thisInstance = new KeyMgtDataHolder();
private KeyMgtService keyMgtService;
public static KeyMgtDataHolder getInstance() {
return thisInstance;
}
public KeyMgtService getKeyMgtService() {
return keyMgtService;
}
public void setKeyMgtService(KeyMgtService keyMgtService) {
this.keyMgtService = keyMgtService;
}
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtService;
import org.wso2.carbon.apimgt.keymgt.extension.service.KeyMgtServiceImpl;
/**
* @scr.component name="org.wso2.carbon.apimgt.keymgt.extension.keyMgtServiceComponent" immediate="true"
*/
public class KeyMgtServiceComponent {
private static final Log log = LogFactory.getLog(KeyMgtServiceComponent.class);
@SuppressWarnings("unused")
protected void activate(ComponentContext componentContext) {
try {
if (log.isDebugEnabled()) {
log.debug("Initializing key management bundle");
}
BundleContext bundleContext = componentContext.getBundleContext();
KeyMgtService keyMgtService = new KeyMgtServiceImpl();
bundleContext.registerService(KeyMgtService.class.getName(), keyMgtService, null);
KeyMgtDataHolder.getInstance().setKeyMgtService(keyMgtService);
if (log.isDebugEnabled()) {
log.debug("Key management bundle has been successfully initialized");
}
} catch (Throwable e) {
log.error("Error occurred while initializing key management bundle", e);
}
}
@SuppressWarnings("unused")
protected void deactivate(ComponentContext componentContext) {
if (log.isDebugEnabled()) {
log.debug("De-activating Key Management Service Component");
}
}
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.service;
import org.wso2.carbon.apimgt.keymgt.extension.DCRResponse;
import org.wso2.carbon.apimgt.keymgt.extension.TokenRequest;
import org.wso2.carbon.apimgt.keymgt.extension.TokenResponse;
import org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
public interface KeyMgtService {
/***
* This method will handle the DCR requests for applications
*
* @param clientName client name of the application
* @param owner owner of the application
* @param grantTypes grant types to be provided
* @param callBackUrl callback url of the application
* @param tags api tags for api subscription of the application
* @param isSaasApp if the application is a saas app
* @return @{@link DCRResponse} DCR Response object with client credentials
* @throws KeyMgtException if any error occurs during DCR process
*/
DCRResponse dynamicClientRegistration(String clientName, String owner, String grantTypes, String callBackUrl,
String[] tags, boolean isSaasApp) throws KeyMgtException;
/***
* This method will handle the access token requests
*
* @param tokenRequest token request object
* @return @{@link TokenResponse} Access token information
* @throws KeyMgtException if any errors occurred while generating access token
* @throws BadRequestException if any parameters provided are invalid
*/
TokenResponse generateAccessToken(TokenRequest tokenRequest) throws KeyMgtException, BadRequestException;
}

@ -0,0 +1,492 @@
/*
* Copyright (c) 2022, Entgra (Pvt) Ltd. (http://www.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.
*/
package org.wso2.carbon.apimgt.keymgt.extension.service;
import com.google.gson.Gson;
import okhttp3.Credentials;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.api.APIConsumer;
import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.model.APIKey;
import org.wso2.carbon.apimgt.api.model.Application;
import org.wso2.carbon.apimgt.impl.APIManagerFactory;
import org.wso2.carbon.apimgt.impl.utils.APIUtil;
import org.wso2.carbon.apimgt.keymgt.extension.DCRResponse;
import org.wso2.carbon.apimgt.keymgt.extension.KeyManagerPayload;
import org.wso2.carbon.apimgt.keymgt.extension.KeyMgtConstants;
import org.wso2.carbon.apimgt.keymgt.extension.OAuthApplication;
import org.wso2.carbon.apimgt.keymgt.extension.TokenRequest;
import org.wso2.carbon.apimgt.keymgt.extension.TokenResponse;
import org.wso2.carbon.apimgt.keymgt.extension.exception.BadRequestException;
import org.wso2.carbon.apimgt.keymgt.extension.exception.KeyMgtException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig;
import org.wso2.carbon.device.mgt.core.config.keymanager.KeyManagerConfigurations;
import org.wso2.carbon.user.api.UserRealm;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class KeyMgtServiceImpl implements KeyMgtService {
private static final Log log = LogFactory.getLog(KeyMgtServiceImpl.class);
private static final OkHttpClient client = getOkHttpClient();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final Gson gson = new Gson();
private KeyManagerConfigurations kmConfig = null;
RealmService realmService = null;
String subTenantUserUsername, subTenantUserPassword, keyManagerName, msg = null;
public DCRResponse dynamicClientRegistration(String clientName, String owner, String grantTypes, String callBackUrl,
String[] tags, boolean isSaasApp) throws KeyMgtException {
String tenantDomain = MultitenantUtils.getTenantDomain(owner);
int tenantId;
try {
tenantId = getRealmService()
.getTenantManager().getTenantId(tenantDomain);
} catch (UserStoreException e) {
msg = "Error while loading tenant configuration";
log.error(msg);
throw new KeyMgtException(msg);
}
kmConfig = getKeyManagerConfig();
if (KeyMgtConstants.SUPER_TENANT.equals(tenantDomain)) {
OAuthApplication superTenantOauthApp = createOauthApplication(
KeyMgtConstants.RESERVED_OAUTH_APP_NAME_PREFIX + KeyMgtConstants.SUPER_TENANT,
kmConfig.getAdminUsername(), tags);
return new DCRResponse(superTenantOauthApp.getClientId(), superTenantOauthApp.getClientSecret());
} else {
// super-tenant admin dcr and token generation
OAuthApplication superTenantOauthApp = createOauthApplication(
KeyMgtConstants.RESERVED_OAUTH_APP_NAME_PREFIX + KeyMgtConstants.SUPER_TENANT,
kmConfig.getAdminUsername(), null);
String superAdminAccessToken = createAccessToken(superTenantOauthApp);
// create new key manager for the tenant, under super-tenant space
createKeyManager(tenantId, tenantDomain, superAdminAccessToken);
// create a sub-tenant user
try {
subTenantUserUsername = getRealmService()
.getTenantUserRealm(tenantId).getRealmConfiguration()
.getRealmProperty("reserved_tenant_user_username") + "@" + tenantDomain;
subTenantUserPassword = getRealmService()
.getTenantUserRealm(tenantId).getRealmConfiguration()
.getRealmProperty("reserved_tenant_user_password");
} catch (UserStoreException e) {
msg = "Error while loading user realm configuration";
log.error(msg);
throw new KeyMgtException(msg);
}
createUserIfNotExists(subTenantUserUsername, subTenantUserPassword);
// DCR for the requesting user
OAuthApplication dcrApplication = createOauthApplication(clientName, owner, tags);
String requestingUserAccessToken = createAccessToken(dcrApplication);
// get application id
Application application = getApplication(clientName, owner);
String applicationUUID = application.getUUID();
// do app key mapping
mapApplicationKeys(dcrApplication.getClientId(), dcrApplication.getClientSecret(), keyManagerName,
applicationUUID, requestingUserAccessToken);
return new DCRResponse(dcrApplication.getClientId(), dcrApplication.getClientSecret());
}
}
public TokenResponse generateAccessToken(TokenRequest tokenRequest) throws KeyMgtException, BadRequestException {
try {
Application application = APIUtil.getApplicationByClientId(tokenRequest.getClientId());
String tenantDomain = MultitenantUtils.getTenantDomain(application.getOwner());
String username, password;
if (KeyMgtConstants.SUPER_TENANT.equals(tenantDomain)) {
kmConfig = getKeyManagerConfig();
username = kmConfig.getAdminUsername();
password = kmConfig.getAdminUsername();
} else {
try {
username = getRealmService()
.getTenantUserRealm(-1234).getRealmConfiguration()
.getRealmProperty("reserved_tenant_user_username") + "@" + tenantDomain;
password = getRealmService()
.getTenantUserRealm(-1234).getRealmConfiguration()
.getRealmProperty("reserved_tenant_user_password");
} catch (UserStoreException e) {
msg = "Error while loading user realm configuration";
log.error(msg);
throw new KeyMgtException(msg);
}
}
JSONObject jsonObject = new JSONObject();
if ("client_credentials".equals(tokenRequest.getGrantType())) {
jsonObject.put("grant_type", "password");
jsonObject.put("username", username);
jsonObject.put("password", password);
} else if ("refresh_token".equals(tokenRequest.getGrantType())) {
jsonObject.put("grant_type", "refresh_token");
jsonObject.put("refresh_token", tokenRequest.getRefreshToken());
} else {
msg = "Invalid grant type: " + tokenRequest.getGrantType();
throw new BadRequestException(msg);
}
jsonObject.put("scope", tokenRequest.getScope());
RequestBody appTokenPayload = RequestBody.Companion.create(jsonObject.toString(), JSON);
kmConfig = getKeyManagerConfig();
String appTokenEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
Request request = new Request.Builder()
.url(appTokenEndpoint)
.addHeader(KeyMgtConstants.AUTHORIZATION_HEADER, Credentials.basic(tokenRequest.getClientId(), tokenRequest.getClientSecret()))
.post(appTokenPayload)
.build();
Response response = client.newCall(request).execute();
jsonObject = new JSONObject(response.body().string());
String accessToken;
if (KeyMgtConstants.SUPER_TENANT.equals(tenantDomain)) {
accessToken = jsonObject.getString("access_token");
} else {
int tenantId = getRealmService()
.getTenantManager().getTenantId(tenantDomain);
accessToken = tenantId + "_" + jsonObject.getString("access_token");
}
return new TokenResponse(accessToken,
jsonObject.getString("refresh_token"),
jsonObject.getString("scope"),
jsonObject.getString("token_type"),
jsonObject.getInt("expires_in"));
} catch (APIManagementException e) {
msg = "Error occurred while retrieving application";
log.error(msg);
throw new KeyMgtException(msg);
} catch (IOException e) {
msg = "Error occurred while mapping application keys";
log.error(msg);
throw new KeyMgtException(msg);
} catch (UserStoreException e) {
msg = "Error occurred while fetching tenant id";
log.error(msg);
throw new KeyMgtException(msg);
}
}
/***
* Maps the application's keys with the given key manager
*
* @param consumerKey consumer key of the application
* @param consumerSecret consumer secret of the application
* @param keyManager key-manager name to which the keys should be mapped with
* @param applicationUUID application's UUID
* @param accessToken access token of the tenant user
* @throws KeyMgtException if an error occurs while mapping application keys with the key-manager
*/
private void mapApplicationKeys(String consumerKey, String consumerSecret, String keyManager,
String applicationUUID, String accessToken) throws KeyMgtException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("consumerKey", consumerKey);
jsonObject.put("consumerSecret", consumerSecret);
jsonObject.put("keyManager", keyManager);
jsonObject.put("keyType", "PRODUCTION");
RequestBody keyMappingPayload = RequestBody.Companion.create(jsonObject.toString(), JSON);
kmConfig = getKeyManagerConfig();
String keyMappingEndpoint = kmConfig.getServerUrl() +
KeyMgtConstants.APPLICATION_KEY_MAPPING_ENDPOINT.replaceAll("<applicationId>", applicationUUID);
Request request = new Request.Builder()
.url(keyMappingEndpoint)
.addHeader(KeyMgtConstants.AUTHORIZATION_HEADER, "Bearer " + accessToken)
.addHeader(KeyMgtConstants.X_WSO2_TENANT_HEADER, KeyMgtConstants.SUPER_TENANT)
.post(keyMappingPayload)
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
msg = "Error occurred while mapping application keys";
throw new KeyMgtException(msg);
}
}
/***
* Creates user if not exists already in the user store
*
* @param username username of the user
* @param password password of the user
* @throws KeyMgtException if any error occurs while fetching tenant details
*/
private void createUserIfNotExists(String username, String password) throws KeyMgtException {
try {
String tenantDomain = MultitenantUtils.getTenantDomain(username);
int tenantId = getRealmService()
.getTenantManager().getTenantId(tenantDomain);
UserRealm userRealm = getRealmService()
.getTenantUserRealm(tenantId);
UserStoreManager userStoreManager = userRealm.getUserStoreManager();
if (!userStoreManager.isExistingUser(MultitenantUtils.getTenantAwareUsername(username))) {
String[] roles = {"admin"};
userStoreManager.addUser(MultitenantUtils.getTenantAwareUsername(username), password, roles, null, "");
}
} catch (UserStoreException e) {
msg = "Error when trying to fetch tenant details";
log.error(msg);
throw new KeyMgtException(msg);
}
}
/***
* Creates an OAuth Application
*
* @param clientName Name of the client application
* @param owner Owner's name of the client application
* @return @{@link OAuthApplication} OAuth application object
* @throws KeyMgtException if any error occurs while creating response object
*/
private OAuthApplication createOauthApplication (String clientName, String owner, String[] tags) throws KeyMgtException {
String oauthAppCreationPayloadStr = createOauthAppCreationPayload(clientName, owner, tags);
RequestBody oauthAppCreationPayload = RequestBody.Companion.create(oauthAppCreationPayloadStr, JSON);
kmConfig = getKeyManagerConfig();
String dcrEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.DCR_ENDPOINT;
String username, password;
if (KeyMgtConstants.SUPER_TENANT.equals(MultitenantUtils.getTenantDomain(owner))) {
username = kmConfig.getAdminUsername();
password = kmConfig.getAdminPassword();
} else {
username = subTenantUserUsername;
password = subTenantUserPassword;
}
Request request = new Request.Builder()
.url(dcrEndpoint)
.addHeader(KeyMgtConstants.AUTHORIZATION_HEADER, Credentials.basic(username, password))
.post(oauthAppCreationPayload)
.build();
try {
Response response = client.newCall(request).execute();
return gson.fromJson(response.body().string(), OAuthApplication.class);
} catch (IOException e) {
msg = "Error occurred while processing the response";
throw new KeyMgtException(msg);
}
}
/***
* Creates access token with client credentials grant type
*
* @param oAuthApp OAuth application object
* @return Access token
* @throws KeyMgtException if any error occurs while reading access token from the response
*/
private String createAccessToken (OAuthApplication oAuthApp) throws KeyMgtException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("grant_type", KeyMgtConstants.CLIENT_CREDENTIALS_GRANT_TYPE);
jsonObject.put("scope", KeyMgtConstants.DEFAULT_ADMIN_SCOPES);
RequestBody accessTokenReqPayload = RequestBody.Companion.create(jsonObject.toString(), JSON);
kmConfig = getKeyManagerConfig();
String tokenEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.OAUTH2_TOKEN_ENDPOINT;
Request request = new Request.Builder()
.url(tokenEndpoint)
.addHeader(KeyMgtConstants.AUTHORIZATION_HEADER, Credentials.basic(oAuthApp.getClientId(), oAuthApp.getClientSecret()))
.post(accessTokenReqPayload)
.build();
try {
Response response = client.newCall(request).execute();
jsonObject = new JSONObject(response.body().string());
return jsonObject.getString("access_token");
} catch (IOException e) {
msg = "Error occurred while reading access token from response";
throw new KeyMgtException(msg);
}
}
/***
* Creates a key manager for a given tenant, under super-tenant space
*
* @param tenantId tenant-id of the key-manager
* @param tenantDomain tenant domain of the key-manager
* @param accessToken access token of the super-tenant user
* @throws KeyMgtException if any error occurs while creating a key-manager
*/
private void createKeyManager(int tenantId, String tenantDomain, String accessToken) throws KeyMgtException {
try {
List<String> kmGrantTypes = new ArrayList<>();
kmGrantTypes.add("client_credentials");
kmConfig = getKeyManagerConfig();
Map<String, Object> additionalProperties = new HashMap<>();
additionalProperties.put("Username", kmConfig.getAdminUsername());
additionalProperties.put("Password", kmConfig.getAdminPassword());
additionalProperties.put("self_validate_jwt", true);
keyManagerName = generateCustomKeyManagerName(tenantDomain);
KeyManagerPayload keyManagerPayload = new KeyManagerPayload(
tenantDomain, tenantId, kmConfig.getServerUrl(),
keyManagerName, kmGrantTypes, additionalProperties
);
String createKeyManagerPayload = gson.toJson(keyManagerPayload);
RequestBody requestBody = RequestBody.Companion.create(createKeyManagerPayload, JSON);
String keyManagerEndpoint = kmConfig.getServerUrl() + KeyMgtConstants.CREATE_KEY_MANAGER_ENDPOINT;
Request request = new Request.Builder()
.url(keyManagerEndpoint)
.addHeader(KeyMgtConstants.AUTHORIZATION_HEADER, "Bearer " + accessToken)
.post(requestBody)
.build();
client.newCall(request).execute();
} catch (IOException e) {
msg = "Error occurred while invoking create key manager endpoint";
log.error(msg);
throw new KeyMgtException(msg);
}
}
/***
* Retrieves an application by name and owner
*
* @param applicationName name of the application
* @param owner owner of the application
* @return @{@link Application} Application object
* @throws KeyMgtException if any error occurs while retrieving the application
*/
private Application getApplication(String applicationName, String owner) throws KeyMgtException {
try {
APIManagerFactory apiManagerFactory = APIManagerFactory.getInstance();
APIConsumer apiConsumer = apiManagerFactory.getAPIConsumer(owner);
return apiConsumer.getApplicationsByName(owner, applicationName, "");
} catch (APIManagementException e) {
msg = "Error while trying to retrieve the application";
log.error(msg);
throw new KeyMgtException(msg);
}
}
private String createOauthAppCreationPayload(String clientName, String owner, String[] tags) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("applicationName", clientName);
jsonObject.put("username", owner);
jsonObject.put("tags", tags);
return jsonObject.toString();
}
private String generateCustomKeyManagerName(String tenantDomain) {
return KeyMgtConstants.CUSTOM_KEY_MANAGER_NAME_PREFIX + tenantDomain;
}
private RealmService getRealmService() {
if(realmService == null) {
PrivilegedCarbonContext context = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return (RealmService) context.getOSGiService(RealmService.class, null);
} else {
return realmService;
}
}
private static OkHttpClient getOkHttpClient() {
X509TrustManager trustAllCerts = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
};
return new OkHttpClient.Builder()
.sslSocketFactory(getSimpleTrustedSSLSocketFactory(), trustAllCerts)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}).build();
}
private static SSLSocketFactory getSimpleTrustedSSLSocketFactory() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
return null;
}
}
private KeyManagerConfigurations getKeyManagerConfig() {
if (kmConfig != null) {
return kmConfig;
} else {
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().getDeviceManagementConfig();
return deviceManagementConfig.getKeyManagerConfigurations();
}
}
}

@ -38,6 +38,7 @@
<module>org.wso2.carbon.apimgt.application.extension.api</module>
<module>org.wso2.carbon.apimgt.annotations</module>
<module>org.wso2.carbon.apimgt.keymgt.extension</module>
<module>org.wso2.carbon.apimgt.keymgt.extension.api</module>
</modules>
<build>

@ -75,6 +75,7 @@ public class OAuthAuthenticator implements WebappAuthenticator {
}
try {
String bearerToken = getBearerToken(request);
bearerToken = bearerToken.substring(bearerToken.indexOf("_")+1);
String resource = requestUri + ":" + requestMethod;
OAuthValidationResponse oAuthValidationResponse = this.tokenValidator.validateToken(bearerToken, resource);
authenticationInfo = Utils.setAuthenticationInfo(oAuthValidationResponse, authenticationInfo);

@ -67,6 +67,31 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-jaxrs-war</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt.extension.api</artifactId>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/maven-shared-archive-resources/webapps/</outputDirectory>
<destFileName>api-key-management.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.wso2.maven</groupId>
<artifactId>carbon-p2-plugin</artifactId>

@ -1 +1,3 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.keymgt.extension_${feature.version}/webapps/api-key-management.war,target:${installFolder}/../../deployment/server/webapps/api-key-management.war,overwrite:true);\

@ -343,6 +343,11 @@
<artifactId>io.entgra.analytics.mgt.grafana.proxy.common</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.keymgt.extension.api</artifactId>
<version>${carbon.device.mgt.version}</version>
</dependency>
<!-- Device Management dependencies -->
<!-- Governance dependencies -->

Loading…
Cancel
Save