Add generic logic to jit handlers

issue-10462/secure-pending-operation-6.2
Rajitha Kumara 1 year ago committed by Rajitha Kumara
parent aa4b623283
commit 76064844c4

@ -36,14 +36,25 @@ import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wso2.carbon.utils.CarbonUtils;
import org.xml.sax.SAXException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.Objects;
@WebServlet(
name = "JIT Enrollment callback handler",
@ -62,7 +73,8 @@ public class JITEnrollmentCallbackHandler extends HttpServlet {
private String clientId;
private String clientSecret;
private String scope;
private String JITConfigurationPath;
private JITEnrollmentData JITEnrollmentInfo;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
gatewayUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
@ -71,6 +83,7 @@ public class JITEnrollmentCallbackHandler extends HttpServlet {
keyManagerUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
+ System.getProperty(HandlerConstants.IOT_KM_HOST_ENV_VAR)
+ HandlerConstants.COLON + HandlerUtil.getKeyManagerPort(request.getScheme());
JITConfigurationPath = CarbonUtils.getCarbonConfigDirPath() + File.separator + "jit-config.xml";
HttpSession session = request.getSession(false);
try {
if (session == null) {
@ -84,7 +97,7 @@ public class JITEnrollmentCallbackHandler extends HttpServlet {
return;
}
JITEnrollmentData JITEnrollmentInfo = (JITEnrollmentData)
JITEnrollmentInfo = (JITEnrollmentData)
session.getAttribute(HandlerConstants.SESSION_JIT_ENROLLMENT_DATA_KEY);
if (JITEnrollmentInfo == null) {
response.sendError(HttpStatus.SC_UNAUTHORIZED);
@ -92,8 +105,7 @@ public class JITEnrollmentCallbackHandler extends HttpServlet {
}
applicationName = request.getContextPath().substring(1,
request.getContextPath().indexOf("-ui-request-handler"));
scope = "perm:metadata:view perm:metadata:create perm:metadata:update perm:android:enroll " +
"perm:device:enroll perm:android:view-configuration";
initializeJITEnrollmentConfigurations();
populateApplicationData(registerApplication());
persistAuthData(session, getToken());
response.sendRedirect(JITEnrollmentInfo.getRedirectUrl() + "?ownershipType=" +
@ -104,6 +116,52 @@ public class JITEnrollmentCallbackHandler extends HttpServlet {
}
}
private void initializeJITEnrollmentConfigurations() throws JITEnrollmentException {
try {
File JITConfigurationFile = new File(JITConfigurationPath);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document JITConfigurationDoc = documentBuilder.parse(JITConfigurationFile);
JITConfigurationDoc.getDocumentElement().normalize();
Element enrollmentScopes;
if (Objects.equals(JITEnrollmentInfo.getOs(), "android")) {
enrollmentScopes = (Element) JITConfigurationDoc.
getElementsByTagName("AndroidEnrollmentScopes").item(0);
} else if (Objects.equals(JITEnrollmentInfo.getOs(), "ios")) {
enrollmentScopes = (Element) JITConfigurationDoc.
getElementsByTagName("IOSEnrollmentScopes").item(0);
} else if (Objects.equals(JITEnrollmentInfo.getOs(), "windows")) {
enrollmentScopes = (Element) JITConfigurationDoc.
getElementsByTagName("IOSEnrollmentScopes").item(0);
} else {
String msg = "OS type not supported";
if (log.isDebugEnabled()) {
log.error(msg);
}
throw new JITEnrollmentException(msg);
}
NodeList scopeList = enrollmentScopes.getElementsByTagName("Scope");
StringBuilder scopeStr = new StringBuilder();
for (int idx = 0; idx < scopeList.getLength(); idx++) {
Node scopeNode = scopeList.item(idx);
if (scopeNode.getNodeType() == Node.ELEMENT_NODE) {
Element scopeElement = (Element) scopeNode;
scopeStr.append(" ").append(scopeElement.getTextContent());
}
}
scope = scopeStr.toString();
} catch (ParserConfigurationException ex) {
String msg = "Error occurred when document builder creating the file configuration";
throw new JITEnrollmentException(msg, ex);
} catch (IOException ex) {
String msg = "IO error occurred while parsing the JIT config file";
throw new JITEnrollmentException(msg, ex);
} catch (SAXException ex) {
String msg = "Parse error occurred while parsing the JIT config document";
throw new JITEnrollmentException(msg, ex);
}
}
/***
* Parse string data and build json object
* @param data - Json string

@ -19,10 +19,14 @@
package io.entgra.device.mgt.core.ui.request.interceptor;
import io.entgra.device.mgt.core.ui.request.interceptor.beans.JITEnrollmentData;
import io.entgra.device.mgt.core.ui.request.interceptor.exceptions.JITEnrollmentException;
import io.entgra.device.mgt.core.ui.request.interceptor.util.HandlerConstants;
import io.entgra.device.mgt.core.ui.request.interceptor.util.HandlerUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.utils.CarbonUtils;
import org.xml.sax.SAXException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@ -45,7 +49,6 @@ public class JITEnrollmentHandler extends HttpServlet {
private String os;
private String redirectUrl;
private String tenantDomain;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
try {

@ -65,14 +65,10 @@ import java.util.Objects;
public class JITProvisionHandler extends HttpServlet {
private static final Log log = LogFactory.getLog(JITProvisionHandler.class);
private String tenantDomain;
private String adminUsername;
private String clientId;
private String JITServiceProviderName;
private String apiManagerUrl;
private String encodedAdminCredentials;
private String encodedClientCredentials;
private String JITConfigurationPath;
private String JITCallbackUrl;
private String redirectUrl;
@Override
@ -80,14 +76,11 @@ public class JITProvisionHandler extends HttpServlet {
String keyManagerUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
+ System.getProperty(HandlerConstants.IOT_KM_HOST_ENV_VAR)
+ HandlerConstants.COLON + HandlerUtil.getKeyManagerPort(request.getScheme());
JITCallbackUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
String JITCallbackUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
+ System.getProperty(HandlerConstants.IOT_CORE_HOST_ENV_VAR)
+ HandlerConstants.COLON + HandlerUtil.getCorePort(request.getScheme())
+ request.getContextPath()
+ HandlerConstants.JIT_PROVISION_CALLBACK_URL;
apiManagerUrl = request.getScheme() + HandlerConstants.SCHEME_SEPARATOR
+ System.getProperty(HandlerConstants.IOT_APIM_HOST_ENV_VAR)
+ HandlerConstants.COLON + HandlerUtil.getAPIManagerPort(request.getScheme());
JITConfigurationPath = CarbonUtils.getCarbonConfigDirPath() + File.separator + "jit-config.xml";
String scope = "openid";
tenantDomain = request.getParameter("tenantDomain");
@ -103,7 +96,6 @@ public class JITProvisionHandler extends HttpServlet {
return;
}
populateServiceProvider();
persistJITData(request.getSession(true));
response.sendRedirect(keyManagerUrl + HandlerConstants.AUTHORIZATION_ENDPOINT +
"?response_type=code" +
@ -116,24 +108,6 @@ public class JITProvisionHandler extends HttpServlet {
}
}
/***
* Construct dynamic client registration request
* @return {@link HttpPost} DCR request
*/
private HttpPost buildDCRRequest() {
HttpPost DCRRequest = new HttpPost(apiManagerUrl + HandlerConstants.DCR_URL);
DCRRequest.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
DCRRequest.setHeader(HttpHeaders.AUTHORIZATION, HandlerConstants.BASIC + encodedAdminCredentials);
JsonObject payload = new JsonObject();
payload.addProperty("clientName", JITServiceProviderName);
payload.addProperty("owner", adminUsername);
payload.addProperty("saasApp", true);
payload.addProperty("grantType", HandlerConstants.CODE_GRANT_TYPE);
payload.addProperty("callbackUrl", JITCallbackUrl);
DCRRequest.setEntity(new StringEntity(payload.toString(), ContentType.APPLICATION_JSON));
return DCRRequest;
}
/***
* Retrieve JIT data from current session if session exists, otherwise build and return
* @param session - {@link HttpSession}
@ -158,56 +132,22 @@ public class JITProvisionHandler extends HttpServlet {
session.setAttribute(HandlerConstants.SESSION_JIT_DATA_KEY, JITInfo);
}
/***
* Populate service provider details
* @throws JITProvisionException throws when dcr request fails due to IO exception
*/
private void populateServiceProvider() throws JITProvisionException {
try {
HttpPost DCRRequest = buildDCRRequest();
ProxyResponse proxyResponse = HandlerUtil.execute(DCRRequest);
if (proxyResponse.getCode() == HttpStatus.SC_OK) {
JsonObject serviceProvider = parseResponseData(proxyResponse.getData());
clientId = serviceProvider.get("clientId").getAsString();
String clientSecret = serviceProvider.get("clientSecret").getAsString();
String headerValue = clientId + ':' + clientSecret;
encodedClientCredentials = Base64.getEncoder().encodeToString(headerValue.getBytes());
}
} catch (IOException ex) {
String msg = "Error exception occurred while executing proxy request";
throw new JITProvisionException(msg, ex);
}
}
/***
* Parse string data and build json object
* @param data - Json string
* @return {@link JsonObject} Json object corresponding to provided json string
* @throws JITProvisionException throws when error occurred while parsing
*/
private JsonObject parseResponseData(String data) throws JITProvisionException {
JsonParser parser = new JsonParser();
JsonElement responseData = parser.parse(data);
if (responseData.isJsonObject()) {
return responseData.getAsJsonObject();
}
throw new JITProvisionException("Unexpected response body return");
}
/***
* Find the tenant based configurations and return
* @param tenantDomain - Domain of the tenant
* @param document - Config doc
* @return {@link Element} If config found return configuration element, otherwise null
*/
private Element findTenantConfigs(String tenantDomain, Document document) {
NodeList tenantConfigurations = document.getElementsByTagName("TenantConfiguration");
for (int idx = 0; idx < tenantConfigurations.getLength(); idx++) {
Node configNode = tenantConfigurations.item(idx);
private Element findServiceProvider(String tenantDomain, Document document) {
NodeList serviceProviderConfiguration = document.getElementsByTagName("ServiceProvider");
for (int idx = 0; idx < serviceProviderConfiguration.getLength(); idx++) {
Node configNode = serviceProviderConfiguration.item(idx);
if (configNode.getNodeType() == Node.ELEMENT_NODE) {
Element configElement = (Element) configNode;
if (Objects.equals(configElement.getAttributes().
getNamedItem("tenantDomain").getNodeValue(), tenantDomain)) {
getNamedItem("tenantDomain").getNodeValue(), tenantDomain) &&
Objects.equals(configElement.getAttributes().getNamedItem("name").getNodeValue(),
JITServiceProviderName)) {
return configElement;
}
}
@ -227,12 +167,12 @@ public class JITProvisionHandler extends HttpServlet {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document JITConfigurationDoc = documentBuilder.parse(JITConfigurationFile);
JITConfigurationDoc.getDocumentElement().normalize();
Element tenantConfig = findTenantConfigs(tenantDomain, JITConfigurationDoc);
if (tenantConfig == null) return false;
adminUsername = tenantConfig.getElementsByTagName("AdminUsername").item(0).getTextContent();
String adminPassword = tenantConfig.getElementsByTagName("AdminPassword").item(0).getTextContent();
String headerValue = adminUsername + ":" + adminPassword;
encodedAdminCredentials = Base64.getEncoder().encodeToString(headerValue.getBytes());
Element serviceProvider = findServiceProvider(tenantDomain, JITConfigurationDoc);
if (serviceProvider == null) return false;
clientId = serviceProvider.getElementsByTagName("ClientId").item(0).getTextContent();
String clientSecret = serviceProvider.getElementsByTagName("ClientSecret").item(0).getTextContent();
String headerValue = clientId + ":" + clientSecret;
encodedClientCredentials = Base64.getEncoder().encodeToString(headerValue.getBytes());
return true;
} catch (ParserConfigurationException ex) {
String msg = "Error occurred when document builder creating the file configuration";

@ -18,11 +18,27 @@
~ under the License.
-->
<JITProvisionConfiguration>
<!--
<TenantConfiguration tenantDomain="">
<AdminUsername></AdminUsername>
<AdminPassword></AdminPassword>
</TenantConfiguration>
-->
</JITProvisionConfiguration>
<JITConfiguration>
<EnrollmentConfiguration>
<AndroidEnrollmentScopes>
<Scope>perm:metadata:view</Scope>
<Scope>perm:metadata:create</Scope>
<Scope>perm:metadata:update</Scope>
<Scope>perm:android:enroll</Scope>
<Scope>perm:device:enroll</Scope>
<Scope>perm:android:view-configuration</Scope>
</AndroidEnrollmentScopes>
<IOSEnrollmentScopes>
<!-- <Scope></Scope> -->
</IOSEnrollmentScopes>
<WindowsEnrollmentScopes>
<!-- <Scope></Scope> -->
</WindowsEnrollmentScopes>
</EnrollmentConfiguration>
<ServiceProviderConfiguration>
<!--<ServiceProvider tenantDomain="" name="">
<ClientId></ClientId>
<ClientSecret></ClientSecret>
</ServiceProvider>-->
</ServiceProviderConfiguration>
</JITConfiguration>
Loading…
Cancel
Save