diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml new file mode 100644 index 00000000000..e707cbc5f36 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/pom.xml @@ -0,0 +1,103 @@ + + + + + + apimgt-extensions + org.wso2.carbon.devicemgt + 2.0.6-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.apimgt.handlers + 2.0.6-SNAPSHOT + bundle + WSO2 Carbon - API Security Handler Component + WSO2 Carbon - API Management Security Handler Module + http://wso2.org + + + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.apache.synapse + synapse-core + + + org.apache.ws.security.wso2 + wss4j + + + org.wso2.carbon.devicemgt + org.wso2.carbon.certificate.mgt.core + + + org.json.wso2 + json + + + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + 1.4.0 + true + + + ${project.artifactId} + ${project.artifactId} + ${carbon.device.mgt.version} + WSO2 Carbon - API Security Handler Component + + org.apache.axiom.*, + javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, + javax.xml.*, + org.apache.axis2.*, + org.apache.commons.*, + org.apache.http.*, + org.apache.http.util, + org.apache.ws.*;version="${org.apache.ws.security.wso2.version}", + org.json, + org.wso2.carbon.utils, + org.wso2.carbon.context, + com.google.gson, + org.w3c.dom, + org.apache.synapse, + org.apache.synapse.core.axis2, + org.apache.synapse.rest + + + + + + + + \ No newline at end of file diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.java new file mode 100644 index 00000000000..9b11ab7faf3 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/APIMCertificateMGTExcepton.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers; + +public class APIMCertificateMGTExcepton extends Exception{ + + private static final long serialVersionUID = -37676242646464497L; + + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public APIMCertificateMGTExcepton(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public APIMCertificateMGTExcepton(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public APIMCertificateMGTExcepton(String msg) { + super(msg); + setErrorMessage(msg); + } + + public APIMCertificateMGTExcepton() { + super(); + } + + public APIMCertificateMGTExcepton(Throwable cause) { + super(cause); + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java new file mode 100644 index 00000000000..1d4282f1a52 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/AuthenticationHandler.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers; + +import com.google.gson.Gson; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.description.HandlerDescription; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.rest.AbstractHandler; +import org.wso2.carbon.apimgt.handlers.beans.Certificate; +import org.wso2.carbon.apimgt.handlers.beans.ValidationResponce; +import org.wso2.carbon.apimgt.handlers.config.IOTServerConfiguration; +import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker; +import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse; +import org.wso2.carbon.apimgt.handlers.utils.AuthConstants; +import org.wso2.carbon.apimgt.handlers.utils.Utils; +import org.wso2.carbon.context.PrivilegedCarbonContext; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +public class AuthenticationHandler extends AbstractHandler { + private static final Log log = LogFactory.getLog(AuthenticationHandler.class); + private static HandlerDescription EMPTY_HANDLER_METADATA = new HandlerDescription("API Security Handler"); + private HandlerDescription handlerDesc; + private RESTInvoker restInvoker; + + private IOTServerConfiguration iotServerConfiguration; + + /** + * Setting up configurations at the constructor + */ + public AuthenticationHandler() { + log.info("Engaging API Security Handler.........."); + restInvoker = new RESTInvoker(); + this.handlerDesc = EMPTY_HANDLER_METADATA; + this.iotServerConfiguration = Utils.initConfig(); + } + + @Override + public boolean handleRequest(org.apache.synapse.MessageContext messageContext) { + org.apache.axis2.context.MessageContext axisMC = ((Axis2MessageContext) messageContext).getAxis2MessageContext(); + + String ctxPath = messageContext.getTo().getAddress().trim(); + + if (log.isDebugEnabled()) { + log.debug("Authentication handler invoked by: " + ctxPath); + } + Map headers = (Map) axisMC.getProperty(MessageContext.TRANSPORT_HEADERS); + try { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + RESTResponse response; + if (headers.containsKey(AuthConstants.MDM_SIGNATURE)) { + + String mdmSignature = headers.get(AuthConstants.MDM_SIGNATURE).toString(); + if (log.isDebugEnabled()) { + log.debug("Verify Cert:\n" + mdmSignature); + } + String accessToken = Utils.getAccessToken(iotServerConfiguration); + + String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); + URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); + + Map certVerifyHeaders = new HashMap<>(); + certVerifyHeaders.put("Authorization", "Bearer " + accessToken); + certVerifyHeaders.put("Content-Type", "application/json"); + + Certificate certificate = new Certificate(); + certificate.setPem(mdmSignature); + certificate.setTenantId(tenantId); + certificate.setSerial(""); + + Gson gson = new Gson(); + String certVerifyContent = gson.toJson(certificate); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, + null, certVerifyContent); + + String str = response.getContent(); + if (str.contains("JWTToken")) { + ValidationResponce validationResponce = gson.fromJson(str, ValidationResponce.class); + // TODO: send the JWT token with user details. + // headers.put("X-JWT-Assertion", validationResponce.getJWTToken()); + } + if (log.isDebugEnabled()) { + log.debug("Verify response:" + response.getContent()); + log.debug("Response String : " + str); + } + + } else if (headers.containsKey(AuthConstants.PROXY_MUTUAL_AUTH_HEADER)) { + String subjectDN = headers.get(AuthConstants.PROXY_MUTUAL_AUTH_HEADER).toString(); + + if (log.isDebugEnabled()) { + log.debug("Verify subject DN: " + subjectDN); + } + String accessToken = Utils.getAccessToken(iotServerConfiguration); + String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); + URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); + Map certVerifyHeaders = new HashMap<>(); + certVerifyHeaders.put("Authorization", "Bearer " + accessToken); + certVerifyHeaders.put("Content-Type", "application/json"); + Certificate certificate = new Certificate(); + certificate.setPem(subjectDN); + certificate.setTenantId(tenantId); + certificate.setSerial(AuthConstants.PROXY_MUTUAL_AUTH_HEADER); + + Gson gson = new Gson(); + String certVerifyContent = gson.toJson(certificate); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, + null, certVerifyContent); + if (log.isDebugEnabled()) { + log.debug("Verify response:" + response.getContent()); + } + } else if (headers.containsKey(AuthConstants.ENCODED_PEM)) { + String encodedPem = headers.get(AuthConstants.ENCODED_PEM).toString(); + if (log.isDebugEnabled()) { + log.debug("Verify Cert:\n" + encodedPem); + } + String accessToken = Utils.getAccessToken(iotServerConfiguration); + URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + "android"); + Map certVerifyHeaders = new HashMap<>(); + certVerifyHeaders.put("Authorization", "Bearer " + accessToken); + certVerifyHeaders.put("Content-Type", "application/json"); + + Certificate certificate = new Certificate(); + certificate.setPem(encodedPem); + certificate.setTenantId(tenantId); + certificate.setSerial(""); + Gson gson = new Gson(); + String certVerifyContent = gson.toJson(certificate); + response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, null, + null, certVerifyContent); + if (log.isDebugEnabled()) { + log.debug("Verify response:" + response.getContent()); + } + } else { + log.warn("Unauthorized request for api: " + ctxPath); + return false; + } + if (response != null && !response.getContent().contains("invalid")) { + return true; + } + log.warn("Unauthorized request for api: " + ctxPath); + return false; + } catch (IOException e) { + log.error("Error while processing certificate.", e); + return false; + } catch (URISyntaxException e) { + log.error("Error while processing certificate.", e); + return false; + } catch (APIMCertificateMGTExcepton e) { + log.error("Error while processing certificate.", e); + return false; + } + + } + + @Override + public boolean handleResponse(org.apache.synapse.MessageContext messageContext) { + return true; + } + + + // TODO : take this from the url. + private String getDeviceType(String url) { + if (url.contains("ios")) { + return "ios"; + } else if (url.contains("android")) { + return "android"; + } else return null; + + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java new file mode 100644 index 00000000000..3f0b65f0aeb --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/Certificate.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers.beans; + +public class Certificate { + + private String pem; + private int tenantId; + private String serial; + + public String getPem() { + return pem; + } + + public void setPem(String pem) { + this.pem = pem; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java new file mode 100644 index 00000000000..88ae6de8ce0 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/DCR.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers.beans; + +public class DCR { + + private String owner; + private String clientName; + private String grantType; + private String tokenScope; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getGrantType() { + return grantType; + } + + public void setGrantType(String grantType) { + this.grantType = grantType; + } + + public String getTokenScope() { + return tokenScope; + } + + public void setTokenScope(String tokenScope) { + this.tokenScope = tokenScope; + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java new file mode 100644 index 00000000000..5d698fb5a3c --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/beans/ValidationResponce.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers.beans; + +public class ValidationResponce { + + private String JWTToken; // X-JWT-Assertion + private String deviceId; + private String deviceType; + private int tenantId; + + public String getJWTToken() { + return JWTToken; + } + + public void setJWTToken(String JWTToken) { + this.JWTToken = JWTToken; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java new file mode 100644 index 00000000000..71b430ff405 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/config/IOTServerConfiguration.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers.config; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; +import java.util.List; + +@XmlRootElement(name = "ServerConfiguration") +public class IOTServerConfiguration { + + private String hostname; + private String verificationEndpoint; + private String username; + private String password; + private String dynamicClientRegistrationEndpoint; + private String oauthTokenEndpoint; + private List apis; + + @XmlElement(name = "Hostname", required = true) + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + @XmlElement(name = "VerificationEndpoint", required = true) + public String getVerificationEndpoint() { + return verificationEndpoint; + } + + public void setVerificationEndpoint(String verificationEndpoint) { + this.verificationEndpoint = verificationEndpoint; + } + + @XmlElement(name = "Username", required = true) + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + @XmlElement(name = "Password", required = true) + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @XmlElement(name = "DynamicClientRegistrationEndpoint", required = true) + public String getDynamicClientRegistrationEndpoint() { + return dynamicClientRegistrationEndpoint; + } + + public void setDynamicClientRegistrationEndpoint(String dynamicClientRegistrationEndpoint) { + this.dynamicClientRegistrationEndpoint = dynamicClientRegistrationEndpoint; + } + + @XmlElement(name = "OauthTokenEndpoint", required = true) + public String getOauthTokenEndpoint() { + return oauthTokenEndpoint; + } + + public void setOauthTokenEndpoint(String oauthTokenEndpoint) { + this.oauthTokenEndpoint = oauthTokenEndpoint; + } + + @XmlElementWrapper(name="APIS") + @XmlElement(name = "ContextPath", required = true) + public List getApis() { + return apis; + } + + public void setApis(List apis) { + this.apis = apis; + } + + @XmlRootElement(name = "ContextPath") + public static class ContextPath { + + private String contextPath; + + @XmlValue() + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + } +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java new file mode 100644 index 00000000000..c1d0413a700 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTConstants.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers.invoker; + +public class RESTConstants { + static String REST_CLIENT_CONFIG_ELEMENT = "restClientConfiguration"; + static String REST_CLIENT_MAX_TOTAL_CONNECTIONS = "maxTotalConnections"; + static String REST_CLIENT_MAX_CONNECTIONS_PER_ROUTE = "maxConnectionsPerRoute"; + static String REST_CLEINT_CONNECTION_TIMEOUT = "connectionTimeout"; + static String REST_CLEINT_SOCKET_TIMEOUT = "socketTimeout"; +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java new file mode 100644 index 00000000000..95b4fdecca3 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTInvoker.java @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers.invoker; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.util.AXIOMUtil; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.Header; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.*; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; +import org.wso2.carbon.apimgt.handlers.utils.AuthConstants; +import org.wso2.carbon.apimgt.handlers.utils.CoreUtils; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.Map; + +public class RESTInvoker { + + private static final Log log = LogFactory.getLog(RESTInvoker.class); + + private int maxTotalConnections = 100; + private int maxTotalConnectionsPerRoute = 100; + private int connectionTimeout = 120000; + private int socketTimeout = 120000; + + private CloseableHttpClient client = null; + private PoolingHttpClientConnectionManager connectionManager = null; + + public RESTInvoker() { + configureHttpClient(); + } + +// private void parseConfiguration() { +// String carbonConfigDirPath = CarbonUtils.getCarbonConfigDirPath(); +// String apiFilterConfigPath = carbonConfigDirPath + File.separator + +// AuthConstants.AUTH_CONFIGURATION_FILE_NAME; +// File configFile = new File(apiFilterConfigPath); +// +// try { +// String configContent = FileUtils.readFileToString(configFile); +// OMElement configElement = AXIOMUtil.stringToOM(configContent); +// Iterator beans = configElement.getChildrenWithName( +// new QName("http://www.springframework.org/schema/beans", "bean")); +// +// while (beans.hasNext()) { +// OMElement bean = (OMElement) beans.next(); +// String beanId = bean.getAttributeValue(new QName(null, "id")); +// if (beanId.equals(RESTConstants.REST_CLIENT_CONFIG_ELEMENT)) { +// Iterator beanProps = bean.getChildrenWithName( +// new QName("http://www.springframework.org/schema/beans", "property")); +// +// while (beanProps.hasNext()) { +// OMElement beanProp = (OMElement) beanProps.next(); +// String beanName = beanProp.getAttributeValue(new QName(null, "name")); +// if (RESTConstants.REST_CLIENT_MAX_TOTAL_CONNECTIONS.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// if (value != null && !value.trim().equals("")) { +// maxTotalConnections = Integer.parseInt(value); +// } +// CoreUtils.debugLog(log, "Max total http connections ", maxTotalConnections); +// } else if (RESTConstants.REST_CLIENT_MAX_CONNECTIONS_PER_ROUTE.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// if (value != null && !value.trim().equals("")) { +// maxTotalConnectionsPerRoute = Integer.parseInt(value); +// } +// CoreUtils.debugLog(log, "Max total client connections per route ", maxTotalConnectionsPerRoute); +// } else if (RESTConstants.REST_CLEINT_CONNECTION_TIMEOUT.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// if (value != null && !value.trim().equals("")) { +// connectionTimeout = Integer.parseInt(value); +// } +// } else if (RESTConstants.REST_CLEINT_SOCKET_TIMEOUT.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// if (value != null && !value.trim().equals("")) { +// socketTimeout = Integer.parseInt(value); +// } +// } +// } +// } +// } +// } catch (XMLStreamException e) { +// log.error("Error in processing http connection settings, using default settings", e); +// } catch (IOException e) { +// log.error("Error in processing http connection settings, using default settings", e); +// } +// } + + private void configureHttpClient() { + +// parseConfiguration(); + + RequestConfig defaultRequestConfig = RequestConfig.custom() + .setExpectContinueEnabled(true) + .setConnectTimeout(connectionTimeout) + .setSocketTimeout(socketTimeout) + .build(); + + connectionManager = new PoolingHttpClientConnectionManager(); + connectionManager.setDefaultMaxPerRoute(maxTotalConnectionsPerRoute); + connectionManager.setMaxTotal(maxTotalConnections); + client = HttpClients.custom() + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(defaultRequestConfig) + .build(); + + if(log.isDebugEnabled()){ + log.debug("REST client initialized with " + + "maxTotalConnection = " + maxTotalConnections + + "maxConnectionsPerRoute = " + maxTotalConnectionsPerRoute + + "connectionTimeout = " + connectionTimeout); + } +// +// CoreUtils.debugLog(log, "REST client initialized with ", +// "maxTotalConnection = ", maxTotalConnections, +// "maxConnectionsPerRoute = ", maxTotalConnectionsPerRoute, +// "connectionTimeout = ", connectionTimeout); + } + + public void closeHttpClient() { + IOUtils.closeQuietly(client); + IOUtils.closeQuietly(connectionManager); + } + + /** + * Invokes the http GET method + * + * @param uri endpoint/service url + * @param requestHeaders header list + * @param username username for authentication + * @param password password for authentication + * @return RESTResponse of the GET request (can be the response body or the response status code) + * @throws Exception + */ + public RESTResponse invokeGET(URI uri, Map requestHeaders, String username, String password) throws IOException { + + HttpGet httpGet = null; + CloseableHttpResponse response = null; + Header[] headers; + int httpStatus; + String contentType; + String output; + try { + httpGet = new HttpGet(uri); + if (requestHeaders != null && !requestHeaders.isEmpty()) { + Object keys[] = requestHeaders.keySet().toArray(); + for (Object header : keys) { + httpGet.setHeader(header.toString(), requestHeaders.get(header).toString()); + } + } + response = sendReceiveRequest(httpGet, username, password); + output = IOUtils.toString(response.getEntity().getContent()); + headers = response.getAllHeaders(); + httpStatus = response.getStatusLine().getStatusCode(); + contentType = response.getEntity().getContentType().getValue(); + if (log.isDebugEnabled()) { + log.debug("Invoked GET " + uri.toString() + " - Response message: " + output); + } + EntityUtils.consume(response.getEntity()); + } finally { + if (response != null) { + IOUtils.closeQuietly(response); + } + if (httpGet != null) { + httpGet.releaseConnection(); + } + } + return new RESTResponse(contentType, output, headers, httpStatus); + } + + + public RESTResponse invokePOST(URI uri, Map requestHeaders, String username, + String password, String payload) throws IOException { + + HttpPost httpPost = null; + CloseableHttpResponse response = null; + Header[] headers; + int httpStatus; + String contentType; + String output; + try { + httpPost = new HttpPost(uri); + httpPost.setEntity(new StringEntity(payload)); + if (requestHeaders != null && !requestHeaders.isEmpty()) { + Object keys[] = requestHeaders.keySet().toArray(); + for (Object header : keys) { + httpPost.setHeader(header.toString(), requestHeaders.get(header).toString()); + } + } + response = sendReceiveRequest(httpPost, username, password); + output = IOUtils.toString(response.getEntity().getContent()); + headers = response.getAllHeaders(); + httpStatus = response.getStatusLine().getStatusCode(); + contentType = response.getEntity().getContentType().getValue(); + if (log.isDebugEnabled()) { + log.debug("Invoked POST " + uri.toString() + + " - Input payload: " + payload + " - Response message: " + output); + } + EntityUtils.consume(response.getEntity()); + } finally { + if (response != null) { + IOUtils.closeQuietly(response); + } + if (httpPost != null) { + httpPost.releaseConnection(); + } + } + return new RESTResponse(contentType, output, headers, httpStatus); + } + + /** + * Invokes the http PUT method + * + * @param uri endpoint/service url + * @param requestHeaders header list + * @param username username for authentication + * @param password password for authentication + * @param payload payload body passed + * @return RESTResponse of the PUT request (can be the response body or the response status code) + * @throws Exception + */ + public RESTResponse invokePUT(URI uri, Map requestHeaders, String username, String password, + String payload) throws IOException { + + HttpPut httpPut = null; + CloseableHttpResponse response = null; + Header[] headers; + int httpStatus; + String contentType; + String output; + try { + httpPut = new HttpPut(uri); + httpPut.setEntity(new StringEntity(payload)); + if (requestHeaders != null && !requestHeaders.isEmpty()) { + Object keys[] = requestHeaders.keySet().toArray(); + for (Object header : keys) { + httpPut.setHeader(header.toString(), requestHeaders.get(header).toString()); + } + } + response = sendReceiveRequest(httpPut, username, password); + output = IOUtils.toString(response.getEntity().getContent()); + headers = response.getAllHeaders(); + httpStatus = response.getStatusLine().getStatusCode(); + contentType = response.getEntity().getContentType().getValue(); + if (log.isDebugEnabled()) { + log.debug("Invoked PUT " + uri.toString() + " - Response message: " + output); + } + EntityUtils.consume(response.getEntity()); + } finally { + if (response != null) { + IOUtils.closeQuietly(response); + } + if (httpPut != null) { + httpPut.releaseConnection(); + } + } + return new RESTResponse(contentType, output, headers, httpStatus); + } + + /** + * Invokes the http DELETE method + * + * @param uri endpoint/service url + * @param requestHeaders header list + * @param username username for authentication + * @param password password for authentication + * @return RESTResponse of the DELETE (can be the response status code or the response body) + * @throws Exception + */ + public RESTResponse invokeDELETE(URI uri, Map requestHeaders, String username, String password) throws IOException { + + HttpDelete httpDelete = null; + CloseableHttpResponse response = null; + Header[] headers; + int httpStatus; + String contentType; + String output; + try { + httpDelete = new HttpDelete(uri); + if (requestHeaders != null && !requestHeaders.isEmpty()) { + Object keys[] = requestHeaders.keySet().toArray(); + for (Object header : keys) { + httpDelete.setHeader(header.toString(), requestHeaders.get(header).toString()); + } + } + response = sendReceiveRequest(httpDelete, username, password); + output = IOUtils.toString(response.getEntity().getContent()); + headers = response.getAllHeaders(); + httpStatus = response.getStatusLine().getStatusCode(); + contentType = response.getEntity().getContentType().getValue(); + if (log.isDebugEnabled()) { + log.debug("Invoked DELETE " + uri.toString() + " - Response message: " + output); + } + EntityUtils.consume(response.getEntity()); + } finally { + if (response != null) { + IOUtils.closeQuietly(response); + } + if (httpDelete != null) { + httpDelete.releaseConnection(); + } + } + return new RESTResponse(contentType, output, headers, httpStatus); + } + + private CloseableHttpResponse sendReceiveRequest(HttpRequestBase requestBase, String username, String password) + throws IOException { + CloseableHttpResponse response; + if (username != null && !username.equals("") && password != null) { + String combinedCredentials = username + ":" + password; + byte[] encodedCredentials = Base64.encodeBase64(combinedCredentials.getBytes(StandardCharsets.UTF_8)); + requestBase.addHeader("Authorization", "Basic " + new String(encodedCredentials)); + + response = client.execute(requestBase); + } else { + response = client.execute(requestBase); + } + return response; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java new file mode 100644 index 00000000000..7ce0389baac --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/invoker/RESTResponse.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers.invoker; + +import org.apache.http.Header; + +/** + * RESTResponse class holds the data retrieved from the HTTP invoke response. + */ +public class RESTResponse { + private String contentType; + private String content; + private Header[] headers; + private int httpStatus; + + /** + * Constructor + * + * @param contentType from the REST invoke response + * @param content from the REST invoke response + * @param headers from the REST invoke response + * @param httpStatus from the REST invoke response + */ + public RESTResponse(String contentType, String content, Header[] headers, int httpStatus) { + this.contentType = contentType; + this.content = content; + this.headers = headers; + this.httpStatus = httpStatus; + } + + /** + * Get the content type of the EST invoke response + * + * @return String content type of the response + */ + public String getContentType() { + return contentType; + } + + /** + * Get contents of the REST invoke response + * + * @return contents of the REST invoke response + */ + public String getContent() { + return content; + } + + /** + * Get headers of the REST invoke response + * + * @return headers of the REST invoke response + */ + public Header[] getHeaders() { + return headers; + } + + /** + * Get the HTTP Status code from REST invoke response + * + * @return int HTTP status code + */ + public int getHttpStatus() { + return httpStatus; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java new file mode 100644 index 00000000000..03a8780efc9 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/AuthConstants.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers.utils; + +public class AuthConstants { + public static final String SEC_FAULT = "SECURITY_VALIDATION_FAILURE"; + public static final String HTTPS = "https"; + public static final String WSSE = "wsse"; + public static final String AUTH_CONFIGURATION_FILE_NAME = "api-filter-config.xml"; + public static final String API_FILTER_CONFIG_ELEMENT = "apiFilterConfig"; + public static final String API_LIST_PROPERTY = "apiList"; + public static final String HOST = "host"; + public static final String HTTPS_PORT = "httpsPort"; + public static final String USERNAME = "username"; + public static final String PASSWORD = "password"; + public static final String IOS_VERIFY_ENDPOINT = "ios-verify-endpoint"; + public static final String ANDROID_VERIFY_ENDPOINT = "android-verify-endpoint"; + public static final String MDM_SIGNATURE = "mdm-signature"; + public static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header"; + public static final String ENCODED_PEM = "encoded-pem"; +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java new file mode 100644 index 00000000000..605ad801e6d --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/CoreUtils.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.handlers.utils; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.util.AXIOMUtil; +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +public class CoreUtils { + private static final Log log = LogFactory.getLog(CoreUtils.class); + private static String host = "localhost"; + private static int httpsPort = 9443; + private static String username = "admin"; + private static String password = "admin"; + private static String iosVerifyEndpoint = "/api/certificate-mgt/v1.0/admin/certificates/verify/ios"; + private static String androidVerifyEndpoint = "/api/certificate-mgt/v1.0/admin/certificates/verify/android"; + +// /** +// * Reading configurations from api-filter-config.xml file +// * +// * @return ArrayList of api contexts +// */ +// public static ArrayList readApiFilterList() { +// ArrayList apiList = new ArrayList(); +// String carbonConfigDirPath = CarbonUtils.getCarbonConfigDirPath(); +// String apiFilterConfigPath = carbonConfigDirPath + File.separator + +// AuthConstants.AUTH_CONFIGURATION_FILE_NAME; +// File configFile = new File(apiFilterConfigPath); +// +// try { +// String configContent = FileUtils.readFileToString(configFile); +// OMElement configElement = AXIOMUtil.stringToOM(configContent); +// Iterator beans = configElement.getChildrenWithName( +// new QName("http://www.springframework.org/schema/beans", "bean")); +// +// while (beans.hasNext()) { +// OMElement bean = (OMElement) beans.next(); +// String beanId = bean.getAttributeValue(new QName(null, "id")); +// if (beanId.equals(AuthConstants.API_FILTER_CONFIG_ELEMENT)) { +// Iterator beanProps = bean.getChildrenWithName( +// new QName("http://www.springframework.org/schema/beans", "property")); +// +// while (beanProps.hasNext()) { +// OMElement beanProp = (OMElement) beanProps.next(); +// String beanName = beanProp.getAttributeValue(new QName(null, "name")); +// if (AuthConstants.API_LIST_PROPERTY.equals(beanName)) { +// Iterator apiListSet = ((OMElement) beanProp.getChildrenWithLocalName("set").next()) +// .getChildrenWithLocalName("value"); +// while (apiListSet.hasNext()) { +// String apiContext = ((OMElement) apiListSet.next()).getText(); +// apiList.add(apiContext); +// CoreUtils.debugLog(log, "Adding security to api: ", apiContext); +// } +// } else if (AuthConstants.HOST.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// host = value; +// } else if (AuthConstants.HTTPS_PORT.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// if (value != null && !value.trim().equals("")) { +// httpsPort = Integer.parseInt(value); +// } +// } else if (AuthConstants.USERNAME.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// username = value; +// } else if (AuthConstants.PASSWORD.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// password = value; +// } else if (AuthConstants.IOS_VERIFY_ENDPOINT.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// iosVerifyEndpoint = value; +// } else if (AuthConstants.ANDROID_VERIFY_ENDPOINT.equals(beanName)) { +// String value = beanProp.getAttributeValue(new QName(null, "value")); +// androidVerifyEndpoint = value; +// } +// } +// } +// } +// } catch (IOException e) { +// log.error("Error in reading api filter settings", e); +// } catch (XMLStreamException e) { +// log.error("Error in reading api filter settings", e); +// } +// return apiList; +// } +// +// /** +// * Universal debug log function +// * +// * @param logger Log object specific to the class +// * @param message initial debug log message +// * @param vars optional strings to be appended for the log +// */ +// public static void debugLog(Log logger, String message, Object ... vars) { +// if(logger.isDebugEnabled()) { +// if (vars.length < 1) { +// logger.debug(message); +// return; +// } +// StringBuilder stringBuilder = new StringBuilder(); +// stringBuilder.append(message); +// for (Object var : vars) { +// stringBuilder.append(var.toString()); +// } +// logger.debug(stringBuilder.toString()); +// } +// } + + public static String getHost() { + return host; + } + + public static int getHttpsPort() { + return httpsPort; + } + + public static String getUsername() { + return username; + } + + public static String getPassword() { + return password; + } + + public static String getIosVerifyEndpoint() { + return iosVerifyEndpoint; + } + + public static String getAndroidVerifyEndpoint() { + return androidVerifyEndpoint; + } +} diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java new file mode 100644 index 00000000000..416ae306ae9 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org.wso2.carbon.apimgt.handlers/utils/Utils.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.handlers.utils; + +import com.google.gson.Gson; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ws.security.util.Base64; +import org.json.JSONException; +import org.json.JSONObject; +import org.w3c.dom.Document; +import org.wso2.carbon.apimgt.handlers.APIMCertificateMGTExcepton; +import org.wso2.carbon.apimgt.handlers.beans.DCR; +import org.wso2.carbon.apimgt.handlers.config.IOTServerConfiguration; +import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker; +import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +public class Utils { + + private static final Log log = LogFactory.getLog(Utils.class); + private static final String IOT_APIS_CONFIG_FILE = "iot-api-config.xml"; + private static String clientId; + private static String clientSecret; + + public static IOTServerConfiguration initConfig() { + try { + + String IOTServerAPIConfigurationPath = + CarbonUtils.getCarbonConfigDirPath() + File.separator + IOT_APIS_CONFIG_FILE; + File file = new File(IOTServerAPIConfigurationPath); + Document doc = Utils.convertToDocument(file); + + JAXBContext fileContext = JAXBContext.newInstance(IOTServerConfiguration.class); + Unmarshaller unmarshaller = fileContext.createUnmarshaller(); + return (IOTServerConfiguration) unmarshaller.unmarshal(doc); + + } catch (JAXBException | APIMCertificateMGTExcepton e) { + log.error("Error occurred while initializing Data Source config", e); + return null; + } + } + + public static Document convertToDocument(File file) throws APIMCertificateMGTExcepton { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + return docBuilder.parse(file); + } catch (Exception e) { + throw new APIMCertificateMGTExcepton("Error occurred while parsing file, while converting " + + "to a org.w3c.dom.Document", e); + } + } + + public static String getAccessToken(IOTServerConfiguration iotServerConfiguration) + throws APIMCertificateMGTExcepton { + try { + if (clientId == null || clientSecret == null) { + getClientSecretes(iotServerConfiguration); + } + URI tokenUrl = new URI(iotServerConfiguration.getOauthTokenEndpoint()); + String tokenContent = "grant_type=password&username=" + iotServerConfiguration.getUsername()+ "&password=" + + iotServerConfiguration.getPassword() + "&scope=activity-view"; + String tokenBasicAuth = "Basic " + Base64.encode((clientId + ":" + clientSecret).getBytes()); + Map tokenHeaders = new HashMap(); + tokenHeaders.put("Authorization", tokenBasicAuth); + tokenHeaders.put("Content-Type", "application/x-www-form-urlencoded"); + + RESTInvoker restInvoker = new RESTInvoker(); + RESTResponse response = restInvoker.invokePOST(tokenUrl, tokenHeaders, null, + null, tokenContent); + if(log.isDebugEnabled()) { + log.debug("Token response:" + response.getContent()); + } + JSONObject jsonResponse = new JSONObject(response.getContent()); + String accessToken = jsonResponse.getString("access_token"); + return accessToken; + + } catch (URISyntaxException e) { + throw new APIMCertificateMGTExcepton("Error occurred while trying to call oauth token endpoint", e); + } catch (JSONException e) { + throw new APIMCertificateMGTExcepton("Error occurred while converting the json to object", e); + } catch (IOException e) { + throw new APIMCertificateMGTExcepton("Error occurred while trying to call oauth token endpoint", e); + } + } + + private static void getClientSecretes(IOTServerConfiguration iotServerConfiguration) + throws APIMCertificateMGTExcepton { + try { + DCR dcr = new DCR(); + dcr.setOwner(iotServerConfiguration.getUsername()); + dcr.setClientName("IOT-API-MANAGER"); + dcr.setGrantType("refresh_token password client_credentials"); + dcr.setTokenScope("default"); + Gson gson = new Gson(); + String dcrContent = gson.toJson(dcr); + Map drcHeaders = new HashMap(); + drcHeaders.put("Content-Type", "application/json"); + URI dcrUrl = new URI(iotServerConfiguration.getDynamicClientRegistrationEndpoint()); + RESTInvoker restInvoker = new RESTInvoker(); + RESTResponse response = restInvoker.invokePOST(dcrUrl, drcHeaders, null, + null, dcrContent); + + if (log.isDebugEnabled()) { + log.debug("DCR response :" + response.getContent()); + } + JSONObject jsonResponse = new JSONObject(response.getContent()); + clientId = jsonResponse.getString("client_id"); + clientSecret = jsonResponse.getString("client_secret"); + } catch (JSONException e) { + throw new APIMCertificateMGTExcepton("Error occurred while converting the json to object", e); + } catch (IOException e) { + throw new APIMCertificateMGTExcepton("Error occurred while trying to call DCR endpoint", e); + } catch (URISyntaxException e) { + throw new APIMCertificateMGTExcepton("Error occurred while trying to call DCR endpoint", e); + } + + } + +} + diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml new file mode 100644 index 00000000000..fc65693d281 --- /dev/null +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/resources/iot-api-config.xml @@ -0,0 +1,40 @@ + + + + + + https://localhost:9443/ + + + https://localhost:9443/api/certificate-mgt/v1.0/admin/certificates/verify/ + + + admin + admin + + + https://localhost:9443/dynamic-client-web/register + + + https://localhost:9443/oauth2/token + + + /services/echo + + \ No newline at end of file diff --git a/components/apimgt-extensions/pom.xml b/components/apimgt-extensions/pom.xml index 850097bc1b2..b0ef6f0a7b2 100644 --- a/components/apimgt-extensions/pom.xml +++ b/components/apimgt-extensions/pom.xml @@ -38,6 +38,7 @@ org.wso2.carbon.apimgt.application.extension org.wso2.carbon.apimgt.application.extension.api org.wso2.carbon.apimgt.annotations + org.wso2.carbon.apimgt.handlers diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml index 377b33ea3e0..4c572152a9b 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/pom.xml @@ -149,6 +149,11 @@ org.wso2.carbon.certificate.mgt.core provided + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + provided + io.swagger swagger-annotations diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java index 69a10a16d8a..14d06f00f04 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/CertificateManagementAdminService.java @@ -18,6 +18,7 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificat import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; +import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -337,4 +338,125 @@ public interface CertificateManagementAdminService { defaultValue = "12438035315552875930") @PathParam("serialNumber") String serialNumber); +// /** +// * Verify IOS Certificate for the API security filter +// * +// * @param certificate to be verified as a String +// * @return Status of the certificate verification. +// */ +// @POST +// @Path("/verify/ios") +// @ApiOperation( +// consumes = MediaType.APPLICATION_JSON, +// produces = MediaType.APPLICATION_JSON, +// httpMethod = "POST", +// value = "Verify IOS SSL certificate", +// notes = "Verify IOS Certificate for the API security filter.\n", +// tags = "Certificate Management") +// @ApiResponses( +// value = { +// @ApiResponse( +// code = 200, +// message = "Return the status of the IOS certificate verification.", +// responseHeaders = { +// @ResponseHeader( +// name = "Content-Type", +// description = "The content type of the body")}), +// @ApiResponse( +// code = 400, +// message = "Bad Request. \n Invalid request or validation error.", +// response = ErrorResponse.class) +// }) +// Response verifyIOSCertificate( +// @ApiParam( +// name = "certificate", +// value = "The properties to verify certificate. It includes the following: \n" + +// "serial: The unique ID of the certificate. (optional) \n" + +// "pem: mdm-signature of the certificate", +// required = true) EnrollmentCertificate certificate); +// +// /** +// * Verify Android Certificate for the API security filter +// * +// * @param certificate to be verified as a String +// * @return Status of the certificate verification. +// */ +// @POST +// @Path("/verify/android") +// @ApiOperation( +// consumes = MediaType.APPLICATION_JSON, +// produces = MediaType.APPLICATION_JSON, +// httpMethod = "POST", +// value = "Verify Android SSL certificate", +// notes = "Verify Android Certificate for the API security filter.\n", +// tags = "Certificate Management") +// @ApiResponses( +// value = { +// @ApiResponse( +// code = 200, +// message = "Return the status of the Android certificate verification.", +// responseHeaders = { +// @ResponseHeader( +// name = "Content-Type", +// description = "The content type of the body")}), +// @ApiResponse( +// code = 400, +// message = "Bad Request. \n Invalid request or validation error.", +// response = ErrorResponse.class) +// }) +// Response verifyAndroidCertificate( +// @ApiParam( +// name = "certificate", +// value = "The properties to verify certificate. It includes the following: \n" + +// "serial: The unique ID of the certificate. (optional) \n" + +// "pem: pem String of the certificate", +// required = true) EnrollmentCertificate certificate); +// + + + /** + * Verify Android Certificate for the API security filter + * + * @param certificate to be verified as a String + * @return Status of the certificate verification. + */ + @POST + @Path("/verify/{type}") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Verify Android SSL certificate", + notes = "Verify Android Certificate for the API security filter.\n", + tags = "Certificate Management") + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "Return the status of the Android certificate verification.", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body")}), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class) + }) + Response verifyCertificate( + @ApiParam( + name = "type", + value = "The device type, such as ios, android or windows.", + required = true, + allowableValues = "android, ios, windows") + @PathParam("type") + @Size(max = 45) + String type, + @ApiParam( + name = "certificate", + value = "The properties to verify certificate. It includes the following: \n" + + "serial: The unique ID of the certificate. (optional) \n" + + "pem: pem String of the certificate", + required = true) EnrollmentCertificate certificate); } + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java new file mode 100644 index 00000000000..5a72112e4d6 --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans; + +public class ValidationResponce { + + private String JWTToken; // X-JWT-Assertion + private String deviceId; + private String deviceType; + private int tenantId; + + public String getJWTToken() { + return JWTToken; + } + + public void setJWTToken(String JWTToken) { + this.JWTToken = JWTToken; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getDeviceType() { + return deviceType; + } + + public void setDeviceType(String deviceType) { + this.deviceType = deviceType; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } +} + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java index e0f0852787c..0f62d9e72b8 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java @@ -6,14 +6,22 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.CertificateManagementAdmin import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponce; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.CertificateMgtAPIUtils; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.RequestValidationUtil; import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; import org.wso2.carbon.certificate.mgt.core.exception.CertificateManagementException; import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException; +import org.wso2.carbon.certificate.mgt.core.scep.SCEPException; +import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; +import org.wso2.carbon.certificate.mgt.core.scep.TenantedDeviceWrapper; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.certificate.mgt.core.service.PaginationResult; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; import javax.ws.rs.*; import javax.ws.rs.core.Response; @@ -25,6 +33,7 @@ import java.util.List; public class CertificateManagementAdminServiceImpl implements CertificateManagementAdminService { private static Log log = LogFactory.getLog(CertificateManagementAdminServiceImpl.class); + private static final String PROXY_AUTH_MUTUAL_HEADER = "proxy-mutual-auth-header"; /** * Save a list of certificates and relevant information in the database. @@ -138,4 +147,138 @@ public class CertificateManagementAdminServiceImpl implements CertificateManagem } } +// @POST +// @Path("/verify/ios") +// public Response verifyIOSCertificate(@ApiParam(name = "certificate", value = "Mdm-Signature of the " + +// "certificate that needs to be verified", required = true) EnrollmentCertificate certificate) { +// try { +// CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService(); +// X509Certificate cert = certMgtService.extractCertificateFromSignature(certificate.getPem()); +// String challengeToken = certMgtService.extractChallengeToken(cert); +// +// if (challengeToken != null) { +// challengeToken = challengeToken.substring(challengeToken.indexOf("(") + 1).trim(); +// +// SCEPManager scepManager = CertificateMgtAPIUtils.getSCEPManagerService(); +// DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); +// deviceIdentifier.setId(challengeToken); +// deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); +// TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier); +// +// if (tenantedDeviceWrapper != null) { +// return Response.status(Response.Status.OK).entity("valid").build(); +// } +// } +// } catch (SCEPException e) { +// String msg = "Error occurred while extracting information from certificate."; +// log.error(msg, e); +// return Response.serverError().entity( +// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); +// } catch (KeystoreException e) { +// String msg = "Error occurred while converting PEM file to X509Certificate."; +// log.error(msg, e); +// return Response.serverError().entity( +// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); +// } +// return Response.status(Response.Status.OK).entity("invalid").build(); +// } +// +// @POST +// @Path("/verify/android") +// public Response verifyAndroidCertificate(@ApiParam(name = "certificate", value = "Base64 encoded .pem file of the " + +// "certificate that needs to be verified", required = true) EnrollmentCertificate certificate) { +// CertificateResponse certificateResponse = null; +// try { +// CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService(); +// if (certificate.getSerial().toLowerCase().contains(PROXY_AUTH_MUTUAL_HEADER)) { +// certificateResponse = certMgtService.verifySubjectDN(certificate.getPem()); +// } else { +// X509Certificate clientCertificate = certMgtService.pemToX509Certificate(certificate.getPem()); +// if (clientCertificate != null) { +// certificateResponse = certMgtService.verifyPEMSignature(clientCertificate); +// } +// } +// +// if (certificateResponse != null && certificateResponse.getCommonName() != null && !certificateResponse +// .getCommonName().isEmpty()) { +// return Response.status(Response.Status.OK).entity("valid").build(); +// } +// } catch (KeystoreException e) { +// String msg = "Error occurred while converting PEM file to X509Certificate."; +// log.error(msg, e); +// return Response.serverError().entity( +// new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); +// } +// return Response.status(Response.Status.OK).entity("invalid").build(); +// } + + @POST + @Path("/verify/{type}") + public Response verifyCertificate(@PathParam("type") String type, EnrollmentCertificate certificate) { + try { + CertificateManagementService certMgtService = CertificateMgtAPIUtils.getCertificateManagementService(); + + if (DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS.equalsIgnoreCase(type)) { + X509Certificate cert = certMgtService.extractCertificateFromSignature(certificate.getPem()); + String challengeToken = certMgtService.extractChallengeToken(cert); + + if (challengeToken != null) { + challengeToken = challengeToken.substring(challengeToken.indexOf("(") + 1).trim(); + + SCEPManager scepManager = CertificateMgtAPIUtils.getSCEPManagerService(); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(challengeToken); + deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); + TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier); + + JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils.getJwtClientManagerService(); + String jwdToken = jwtClientManagerService.getJWTClient().getJwtToken( + tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner()); + + ValidationResponce validationResponce = new ValidationResponce(); + validationResponce.setDeviceId(challengeToken); + validationResponce.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); + validationResponce.setJWTToken(jwdToken); + validationResponce.setTenantId(tenantedDeviceWrapper.getTenantId()); + + if (tenantedDeviceWrapper != null) { + return Response.status(Response.Status.OK).entity(validationResponce).build(); + } + } + } + + if (DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID.equalsIgnoreCase(type)) { + CertificateResponse certificateResponse = null; + if (certificate.getSerial().toLowerCase().contains(PROXY_AUTH_MUTUAL_HEADER)) { + certificateResponse = certMgtService.verifySubjectDN(certificate.getPem()); + } else { + X509Certificate clientCertificate = certMgtService.pemToX509Certificate(certificate.getPem()); + if (clientCertificate != null) { + certificateResponse = certMgtService.verifyPEMSignature(clientCertificate); + } + } + + if (certificateResponse != null && certificateResponse.getCommonName() != null && !certificateResponse + .getCommonName().isEmpty()) { + return Response.status(Response.Status.OK).entity("valid").build(); + } + } + } catch (SCEPException e) { + String msg = "Error occurred while extracting information from certificate."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); + } catch (KeystoreException e) { + String msg = "Error occurred while converting PEM file to X509Certificate."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); + } catch (JWTClientException e) { + String msg = "Error occurred while converting PEM file to X509Certificate."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build()).build(); + } + return Response.status(Response.Status.OK).entity("invalid").build(); + } } \ No newline at end of file diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java index a96b013b7b5..fc5264c4db4 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/util/CertificateMgtAPIUtils.java @@ -20,9 +20,11 @@ package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; +import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; import javax.ws.rs.core.MediaType; @@ -50,6 +52,37 @@ public class CertificateMgtAPIUtils { } + public static JWTClientManagerService getJwtClientManagerService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) + ctx.getOSGiService(JWTClientManagerService.class, null); + + if (jwtClientManagerService == null) { + String msg = "JWTClientManagerService Management service not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + + return jwtClientManagerService; + } + + + public static SCEPManager getSCEPManagerService() { + + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + SCEPManager scepManagerService = (SCEPManager) + ctx.getOSGiService(SCEPManager.class, null); + + if (scepManagerService == null) { + String msg = "SCEPManagerImpl Management service not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + + return scepManagerService; + } + + public static MediaType getResponseMediaType(String acceptHeader) { MediaType responseMediaType; if (acceptHeader == null || MediaType.WILDCARD.equals(acceptHeader)) { diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml index cbc9281c545..ff4d481e493 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml @@ -51,7 +51,8 @@ ${carbon.device.mgt.version} Device Management Core Bundle - org.wso2.carbon.certificate.mgt.core.internal + org.wso2.carbon.certificate.mgt.core.internal, + org.wso2.carbon.certificate.mgt.core.util org.osgi.framework, @@ -59,7 +60,7 @@ org.apache.commons.logging, javax.security.auth.x500, javax.xml.*, - javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, + javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, org.apache.commons.codec.binary, org.bouncycastle.asn1, org.bouncycastle.asn1.x500, @@ -97,6 +98,7 @@ !org.wso2.carbon.certificate.mgt.core.internal.*, + !org.wso2.carbon.certificate.mgt.core.util, org.wso2.carbon.certificate.mgt.core.* diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf index fb71f60e969..832c1ab2528 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/jaggery.conf @@ -108,7 +108,7 @@ "contextParams" : [ { "name" : "Owasp.CsrfGuard.Config", - "value" : "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties" + "value" : "/repository/conf/security/Owasp.CsrfGuard.dashboard.properties" } ] } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf index 7c5a2d41c9d..f97bae72cfc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/jaggery.conf @@ -71,7 +71,7 @@ "contextParams" : [ { "name" : "Owasp.CsrfGuard.Config", - "value" : "/repository/conf/security/Owasp.CsrfGuard.Carbon.properties" + "value" : "/repository/conf/security/Owasp.CsrfGuard.dashboard.properties" } ] } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js index 2cf9771beab..a18d2efc501 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js @@ -520,7 +520,7 @@ var module = {}; response.sendError(500, msg); return; } - + /** * @type {{sessionId: string, loggedInUser: string, sessionIndex: string, samlToken: * string}} @@ -533,7 +533,7 @@ var module = {}; if (ssoSession.sessionIndex) { module.loadTenant(ssoSession.loggedInUser); var carbonUser = (require("carbon")).server.tenantUser(ssoSession.loggedInUser); - module.loadTenant(ssoSession.loggedInUser); + module.loadTenant(ssoSession.loggedInUser); utils.setCurrentUser(carbonUser.username, carbonUser.domain, carbonUser.tenantId); var scriptArgument = {input: {samlToken: ssoSession.samlToken}, user: module.getCurrentUser()}; handleEvent(OPERATION_LOGIN, EVENT_SUCCESS, scriptArgument); diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index 84d43cec1f3..4d3056bf11a 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -17,7 +17,8 @@ ~ under the License. --> - + org.wso2.carbon.devicemgt webapp-authenticator-framework @@ -81,7 +82,8 @@ org.wso2.carbon.core.util, org.wso2.carbon.identity.base; version="${carbon.identity.imp.pkg.version}", org.wso2.carbon.identity.core.util; version="${carbon.identity.imp.pkg.version}", - org.wso2.carbon.identity.oauth2.*; version="${carbon.identity-inbound-auth-oauth.imp.pkg.version}", + org.wso2.carbon.identity.oauth2.*; + version="${carbon.identity-inbound-auth-oauth.imp.pkg.version}", org.wso2.carbon.tomcat.ext.valves, org.wso2.carbon.user.api, org.wso2.carbon.user.core.service, @@ -111,7 +113,7 @@ org.apache.http.impl.conn, javax.xml.soap; version="${javax.xml.soap.imp.pkg.version}", javax.xml.stream, - org.apache.axiom.*; version="${axiom.osgi.version.range}", + org.apache.axiom.*; version="${axiom.osgi.version.range}", org.wso2.carbon.registry.core.*, org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}", org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}", diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml new file mode 100644 index 00000000000..fceb11b4e1b --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/pom.xml @@ -0,0 +1,106 @@ + + + + + + + org.wso2.carbon.devicemgt + apimgt-extensions-feature + 2.0.6-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.apimgt.handler.server.feature + pom + 2.0.6-SNAPSHOT + WSO2 Carbon - Device Management - APIM handler Server Feature + http://wso2.org + This feature contains the handler for the api authentications + + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.handlers + + + + + + + maven-resources-plugin + 2.6 + + + copy-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + build.properties + p2.inf + + + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + p2-feature-generation + package + + p2-feature-gen + + + org.wso2.carbon.apimgt.handler.server + ../../../features/etc/feature.properties + + + org.wso2.carbon.p2.category.type:server + org.eclipse.equinox.p2.type.group:false + + + + + org.wso2.carbon.devicemgt:org.wso2.carbon.apimgt.handlers:${carbon.device.mgt.version} + + + + + + + + + + + + diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties new file mode 100644 index 00000000000..9c86577d768 --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/build.properties @@ -0,0 +1 @@ +custom = true diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml new file mode 100644 index 00000000000..c9a210d3bf2 --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/conf/iot-api-config.xml @@ -0,0 +1,40 @@ + + + + + + https://localhost:9443/ + + + https://localhost:9443/api/certificate-mgt/v1.0/admin/certificates/verify/ + + + admin + admin + + + https://localhost:9443/dynamic-client-web/register + + + https://localhost:9443/oauth2/token + + + /services + + \ No newline at end of file diff --git a/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/p2.inf b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/p2.inf new file mode 100644 index 00000000000..e7c6acf89f2 --- /dev/null +++ b/features/apimgt-extensions/org.wso2.carbon.apimgt.handler.server.feature/src/main/resources/p2.inf @@ -0,0 +1,2 @@ +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.apimgt.handler.server_${feature.version}/conf/iot-api-config.xml,target:${installFolder}/../../conf/iot-api-config.xml,overwrite:true);\ diff --git a/features/apimgt-extensions/pom.xml b/features/apimgt-extensions/pom.xml index 22f08a718bd..b3d333709f6 100644 --- a/features/apimgt-extensions/pom.xml +++ b/features/apimgt-extensions/pom.xml @@ -37,6 +37,7 @@ org.wso2.carbon.apimgt.webapp.publisher.feature org.wso2.carbon.apimgt.application.extension.feature + org.wso2.carbon.apimgt.handler.server.feature diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp deleted file mode 100644 index a8e6a11569a..00000000000 Binary files a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/.cdm-config.xml.swp and /dev/null differ diff --git a/pom.xml b/pom.xml index 3932c83da8f..e48e296762a 100644 --- a/pom.xml +++ b/pom.xml @@ -314,6 +314,12 @@ org.wso2.carbon.apimgt.application.extension.api ${carbon.device.mgt.version} + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.handlers + ${carbon.device.mgt.version} + @@ -1647,6 +1653,17 @@ jersey-core ${jersey.version} + + + org.apache.synapse + synapse-core + ${org.apache.synapse.version} + + + org.apache.ws.security.wso2 + wss4j + ${org.apache.ws.security.wso2.version} + @@ -2038,6 +2055,10 @@ 1.6.1 + + + 2.1.7-wso2v7 + 1.5.11.wso2v15