From 638c6b12c9a1a9e49a081154d55baeb4e86b547c Mon Sep 17 00:00:00 2001 From: Vigneshan Date: Sat, 23 Jul 2022 17:13:11 +0530 Subject: [PATCH] Fix cross-tenant api subscription issue --- ...ApiApplicationRegistrationServiceImpl.java | 13 +- .../pom.xml | 60 +++ .../keymgt/extension/api/DCRRequest.java | 90 ++++ .../extension/api/KeyManagerService.java | 46 ++ .../extension/api/KeyManagerServiceImpl.java | 77 +++ .../src/main/webapp/META-INF/permissions.xml | 32 ++ .../webapp/META-INF/webapp-classloading.xml | 35 ++ .../src/main/webapp/WEB-INF/cxf-servlet.xml | 37 ++ .../src/main/webapp/WEB-INF/web.xml | 109 ++++ .../pom.xml | 10 +- .../keymgt/extension/CustomKeyManager.java | 49 ++ .../apimgt/keymgt/extension/DCRResponse.java | 45 ++ .../KeyManagerConnectorConfiguration.java | 73 +++ .../keymgt/extension/KeyManagerPayload.java | 333 ++++++++++++ .../keymgt/extension/KeyMgtConstants.java | 52 ++ .../keymgt/extension/MatchingResource.java | 18 + .../keymgt/extension/OAuthApplication.java | 63 +++ .../apimgt/keymgt/extension/TokenRequest.java | 75 +++ .../keymgt/extension/TokenResponse.java | 75 +++ .../exception/BadRequestException.java | 34 ++ .../extension/exception/KeyMgtException.java | 32 ++ .../extension/internal/KeyMgtDataHolder.java | 40 ++ .../internal/KeyMgtServiceComponent.java | 62 +++ .../extension/service/KeyMgtService.java | 53 ++ .../extension/service/KeyMgtServiceImpl.java | 492 ++++++++++++++++++ components/apimgt-extensions/pom.xml | 1 + .../authenticator/OAuthAuthenticator.java | 1 + .../pom.xml | 25 + .../src/main/resources/p2.inf | 2 + pom.xml | 5 + 30 files changed, 2030 insertions(+), 9 deletions(-) create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/pom.xml create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/DCRRequest.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerService.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerServiceImpl.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/permissions.xml create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/webapp-classloading.xml create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/cxf-servlet.xml create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/web.xml create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/CustomKeyManager.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/DCRResponse.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerConnectorConfiguration.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerPayload.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyMgtConstants.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/OAuthApplication.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenRequest.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenResponse.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/BadRequestException.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/KeyMgtException.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtDataHolder.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtServiceComponent.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtService.java create mode 100644 components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtServiceImpl.java diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java index 471136864a..8b48346e6e 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java @@ -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 } } -} \ No newline at end of file +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/pom.xml new file mode 100644 index 0000000000..dc93695b1d --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/pom.xml @@ -0,0 +1,60 @@ + + + + apimgt-extensions + org.wso2.carbon.devicemgt + 5.0.11-SNAPSHOT + + + 4.0.0 + org.wso2.carbon.apimgt.keymgt.extension.api + war + WSO2 Carbon - API Key Management API + This module extends the API manager's key management apis. + http://wso2.org + + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + maven-war-plugin + + WEB-INF/lib/*cxf*.jar + ${project.artifactId} + + + + + + + + org.springframework + spring-web + provided + + + org.apache.cxf + cxf-bundle-jaxrs + provided + + + org.codehaus.jackson + jackson-jaxrs + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.keymgt.extension + ${carbon.device.mgt.version} + provided + + + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/DCRRequest.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/DCRRequest.java new file mode 100644 index 0000000000..36f6c4d9f7 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/DCRRequest.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerService.java new file mode 100644 index 0000000000..14ca64a2e6 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerService.java @@ -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); +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerServiceImpl.java new file mode 100644 index 0000000000..53b2c4ffca --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/api/KeyManagerServiceImpl.java @@ -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(); + } + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/permissions.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/permissions.xml new file mode 100644 index 0000000000..190a634a12 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/permissions.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/webapp-classloading.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 0000000000..9f50930c4f --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,35 @@ + + + + + + + + + false + + + CXF3,Carbon + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 0000000000..6d5685c5f5 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/web.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..fe5ca1742e --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.api/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,109 @@ + + + + Grafana-API-Proxy-Webapp + + JAX-WS/JAX-RS Grafana API Management Endpoint + JAX-WS/JAX-RS Servlet + CXFServlet + + org.apache.cxf.transport.servlet.CXFServlet + + + + swagger.security.filter + ApiAuthorizationFilterImpl + + 1 + + + CXFServlet + /* + + + 60 + + + + doAuthentication + false + + + basicAuth + false + + + + nonSecuredEndPoints + + /keymgt-test-api/.*, + + + + + + managed-api-enabled + true + + + managed-api-owner + admin + + + isSharedWithAllTenants + true + + + + HttpHeaderSecurityFilter + org.apache.catalina.filters.HttpHeaderSecurityFilter + + hstsEnabled + false + + + + + ContentTypeBasedCachePreventionFilter + org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter + + patterns + text/html" ,application/json" ,text/plain + + + filterAction + enforce + + + httpHeaders + Cache-Control: no-store, no-cache, must-revalidate, private + + + + + HttpHeaderSecurityFilter + /* + + + + ContentTypeBasedCachePreventionFilter + /* + + + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/pom.xml index e90923172b..f53e5d05e0 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/pom.xml @@ -43,7 +43,7 @@ org.apache.felix maven-bundle-plugin - 1.4.0 + 5.1.7 true @@ -51,10 +51,16 @@ ${project.artifactId} ${carbon.device.mgt.version} API Management Application Bundle + org.wso2.carbon.apimgt.keymgt.extension.internal + org.wso2.carbon.apimgt.application.extension, + org.wso2.carbon.apimgt.application.extension.*, + org.wso2.carbon.device.mgt.common.*, + org.wso2.carbon.device.mgt.core.* - org.wso2.carbon.apimgt.keymgt.extension + !org.wso2.carbon.apimgt.keymgt.extension.internal, + org.wso2.carbon.apimgt.keymgt.extension.* diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/CustomKeyManager.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/CustomKeyManager.java new file mode 100644 index 0000000000..eca37026d9 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/CustomKeyManager.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/DCRResponse.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/DCRResponse.java new file mode 100644 index 0000000000..22dc2336a6 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/DCRResponse.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerConnectorConfiguration.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerConnectorConfiguration.java new file mode 100644 index 0000000000..e68d69bfb0 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerConnectorConfiguration.java @@ -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 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 getConnectionConfigurations() { + List 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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerPayload.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerPayload.java new file mode 100644 index 0000000000..47d254ad6c --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyManagerPayload.java @@ -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 certificates; + private String issuer; + private String scopeManagementEndpoint; + private List availableGrantTypes; + private boolean enableTokenGeneration; + private boolean enableTokenEncryption; + private boolean enableTokenHashing; + private boolean enableMapOAuthConsumerApps; + private boolean enableOAuthAppCreation; + private boolean enableSelfValidationJWT; + private List claimMapping; + private String consumerKeyClaim; + private String scopesClaim; + private List> tokenValidation; + private boolean enabled; + private Map additionalProperties; + + public KeyManagerPayload(String domainName, int tenantId, String serverUrl, String name, + List availableGrantTypes, Map 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 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> tokenValidationList = new ArrayList<>(); + Map tokenValidation = new HashMap<>(); + tokenValidation.put("type", KeyMgtConstants.REFERENCE); + tokenValidation.put("value", KeyMgtConstants.TOKEN_REGEX.replaceAll("<>", 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 getCertificates() { + return certificates; + } + + public void setCertificates(Map 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 getAvailableGrantTypes() { + return availableGrantTypes; + } + + public void setAvailableGrantTypes(List 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 getClaimMapping() { + return claimMapping; + } + + public void setClaimMapping(List 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> getTokenValidation() { + return tokenValidation; + } + + public void setTokenValidation(List> tokenValidation) { + this.tokenValidation = tokenValidation; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Map getAdditionalProperties() { + return additionalProperties; + } + + public void setAdditionalProperties(Map additionalProperties) { + this.additionalProperties = additionalProperties; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyMgtConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyMgtConstants.java new file mode 100644 index 0000000000..c898a40ff0 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/KeyMgtConstants.java @@ -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 = + "^<>*_[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//map-keys"; + public static final String APPLICATION_TOKEN_ENDPOINT = + "/api/am/devportal/v2/applications//oauth-keys//generate-token"; +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/MatchingResource.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/MatchingResource.java index 1fe0723800..04a3173a7f 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/MatchingResource.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/MatchingResource.java @@ -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 { diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/OAuthApplication.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/OAuthApplication.java new file mode 100644 index 0000000000..356d482ceb --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/OAuthApplication.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenRequest.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenRequest.java new file mode 100644 index 0000000000..8ab5c3da35 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenRequest.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenResponse.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenResponse.java new file mode 100644 index 0000000000..8373d7f8f1 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/TokenResponse.java @@ -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; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/BadRequestException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/BadRequestException.java new file mode 100644 index 0000000000..43566f198a --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/BadRequestException.java @@ -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); + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/KeyMgtException.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/KeyMgtException.java new file mode 100644 index 0000000000..47d0927a40 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/exception/KeyMgtException.java @@ -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); + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtDataHolder.java new file mode 100644 index 0000000000..830c36faad --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtDataHolder.java @@ -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; + } + +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtServiceComponent.java new file mode 100644 index 0000000000..e20d6a4b51 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/internal/KeyMgtServiceComponent.java @@ -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"); + } + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtService.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtService.java new file mode 100644 index 0000000000..a9aa2d346a --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtService.java @@ -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; +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtServiceImpl.java new file mode 100644 index 0000000000..23daf8dfdd --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension/src/main/java/org/wso2/carbon/apimgt/keymgt/extension/service/KeyMgtServiceImpl.java @@ -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("", 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 kmGrantTypes = new ArrayList<>(); + kmGrantTypes.add("client_credentials"); + + kmConfig = getKeyManagerConfig(); + Map 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(); + } + } +} diff --git a/components/apimgt-extensions/pom.xml b/components/apimgt-extensions/pom.xml index c7c769180d..ff2b5517de 100644 --- a/components/apimgt-extensions/pom.xml +++ b/components/apimgt-extensions/pom.xml @@ -38,6 +38,7 @@ org.wso2.carbon.apimgt.application.extension.api org.wso2.carbon.apimgt.annotations org.wso2.carbon.apimgt.keymgt.extension + org.wso2.carbon.apimgt.keymgt.extension.api diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java index 9735f054e9..6a5cc3b318 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OAuthAuthenticator.java @@ -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); diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/pom.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/pom.xml index 078914903a..7605b19296 100644 --- a/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/pom.xml +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/pom.xml @@ -67,6 +67,31 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-jaxrs-war + package + + copy + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.keymgt.extension.api + war + true + ${project.build.directory}/maven-shared-archive-resources/webapps/ + api-key-management.war + + + + + + org.wso2.maven carbon-p2-plugin diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/src/main/resources/p2.inf b/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/src/main/resources/p2.inf index a828a69832..03e2e6eb95 100644 --- a/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/src/main/resources/p2.inf +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.keymgt.extension.feature/src/main/resources/p2.inf @@ -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);\ diff --git a/pom.xml b/pom.xml index 4318441f2c..8df731c2fb 100644 --- a/pom.xml +++ b/pom.xml @@ -343,6 +343,11 @@ io.entgra.analytics.mgt.grafana.proxy.common ${carbon.device.mgt.version} + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.keymgt.extension.api + ${carbon.device.mgt.version} +