5
0
mirror of https://github.com/apache/sqoop.git synced 2025-05-03 15:19:38 +08:00

SQOOP-941: Sqoop2: Do not send sensitive values from server to client

(Abraham Elmahrek via Jarek Jarcec Cecho)
This commit is contained in:
Jarek Jarcec Cecho 2013-03-23 08:03:10 -07:00
parent b94c22919e
commit b49b71235d
21 changed files with 96 additions and 39 deletions

View File

@ -49,7 +49,9 @@ public ConnectionBean read(String serverUrl, Long xid) {
public ValidationBean create(String serverUrl, MConnection connection) {
ConnectionBean connectionBean = new ConnectionBean(connection);
JSONObject connectionJson = connectionBean.extract();
// Extract all form inputs including sensitive inputs
JSONObject connectionJson = connectionBean.extract(false);
String response = super.post(serverUrl + RESOURCE,
connectionJson.toJSONString());
@ -63,7 +65,9 @@ public ValidationBean create(String serverUrl, MConnection connection) {
public ValidationBean update(String serverUrl, MConnection connection) {
ConnectionBean connectionBean = new ConnectionBean(connection);
JSONObject connectionJson = connectionBean.extract();
// Extract all form inputs including sensitive inputs
JSONObject connectionJson = connectionBean.extract(false);
String response = super.put(serverUrl + RESOURCE
+ connection.getPersistenceId(),

View File

@ -49,7 +49,9 @@ public JobBean read(String serverUrl, Long xid) {
public ValidationBean create(String serverUrl, MJob job) {
JobBean jobBean = new JobBean(job);
JSONObject jobJson = jobBean.extract();
// Extract all form inputs including sensitive inputs
JSONObject jobJson = jobBean.extract(false);
String response = super.post(serverUrl + RESOURCE,
jobJson.toJSONString());
@ -63,7 +65,9 @@ public ValidationBean create(String serverUrl, MJob job) {
public ValidationBean update(String serverUrl, MJob job) {
JobBean jobBean = new JobBean(job);
JSONObject jobJson = jobBean.extract();
// Extract all form inputs including sensitive inputs
JSONObject jobJson = jobBean.extract(false);
String response = super.put(serverUrl + RESOURCE + job.getPersistenceId(),
jobJson.toJSONString());

View File

@ -96,7 +96,7 @@ public ResourceBundle getFrameworkBundle() {
@Override
@SuppressWarnings("unchecked")
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONArray array = new JSONArray();
for(MConnection connection : connections) {
@ -108,9 +108,9 @@ public JSONObject extract() {
object.put(UPDATED, connection.getLastUpdateDate().getTime());
object.put(CONNECTOR_ID, connection.getConnectorId());
object.put(CONNECTOR_PART,
extractForms(connection.getConnectorPart().getForms()));
extractForms(connection.getConnectorPart().getForms(), skipSensitive));
object.put(FRAMEWORK_PART,
extractForms(connection.getFrameworkPart().getForms()));
extractForms(connection.getFrameworkPart().getForms(), skipSensitive));
array.add(object);
}

View File

@ -62,7 +62,7 @@ public Map<Long, ResourceBundle> getResourceBundles() {
@SuppressWarnings("unchecked")
@Override
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONArray array = new JSONArray();
@ -73,11 +73,11 @@ public JSONObject extract() {
object.put(NAME, connector.getUniqueName());
object.put(CLASS, connector.getClassName());
object.put(VERSION, connector.getVersion());
object.put(CON_FORMS, extractForms(connector.getConnectionForms().getForms()));
object.put(CON_FORMS, extractForms(connector.getConnectionForms().getForms(), skipSensitive));
JSONObject jobForms = new JSONObject();
for (MJobForms job : connector.getAllJobsForms().values()) {
jobForms.put(job.getType().name(), extractForms(job.getForms()));
jobForms.put(job.getType().name(), extractForms(job.getForms(), skipSensitive));
}
object.put(JOB_FORMS, jobForms);

View File

@ -64,13 +64,13 @@ public ResourceBundle getResourceBundle() {
@SuppressWarnings("unchecked")
@Override
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONArray conForms =
extractForms(framework.getConnectionForms().getForms());
extractForms(framework.getConnectionForms().getForms(), skipSensitive);
JSONObject jobForms = new JSONObject();
for (MJobForms job : framework.getAllJobsForms().values()) {
jobForms.put(job.getType().name(), extractForms(job.getForms()));
jobForms.put(job.getType().name(), extractForms(job.getForms(), skipSensitive));
}
JSONObject result = new JSONObject();

View File

@ -98,7 +98,7 @@ public ResourceBundle getFrameworkBundle() {
@Override
@SuppressWarnings("unchecked")
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONArray array = new JSONArray();
for(MJob job : jobs) {
@ -112,9 +112,9 @@ public JSONObject extract() {
object.put(CONNECTION_ID, job.getConnectionId());
object.put(CONNECTOR_ID, job.getConnectorId());
object.put(CONNECTOR_PART,
extractForms(job.getConnectorPart().getForms()));
extractForms(job.getConnectorPart().getForms(), skipSensitive));
object.put(FRAMEWORK_PART,
extractForms(job.getFrameworkPart().getForms()));
extractForms(job.getFrameworkPart().getForms(), skipSensitive));
array.add(object);
}

View File

@ -21,14 +21,14 @@
public interface JsonBean {
JSONObject extract();
JSONObject extract(boolean skipSensitive);
void restore(JSONObject jsonObject);
public static final JsonBean EMPTY_BEAN = new JsonBean() {
@Override
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
return new JSONObject();
}

View File

@ -61,7 +61,7 @@ public SubmissionBean() {
@Override
@SuppressWarnings("unchecked")
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONObject ret = new JSONObject();
ret.put(JOB, submission.getJobId());

View File

@ -54,7 +54,7 @@ public Throwable getThrowable() {
@Override
@SuppressWarnings("unchecked")
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONObject result = new JSONObject();
result.put(MESSAGE, throwable.getMessage());
@ -77,7 +77,7 @@ public JSONObject extract() {
Throwable cause = throwable.getCause();
if(cause != null) {
ThrowableBean causeBean = new ThrowableBean(cause);
result.put(CAUSE, causeBean.extract());
result.put(CAUSE, causeBean.extract(skipSensitive));
}
return result;

View File

@ -73,7 +73,7 @@ public Long getId() {
}
@SuppressWarnings("unchecked")
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONObject object = new JSONObject();
// Optionally transfer id

View File

@ -54,7 +54,7 @@ public VersionBean() {
@SuppressWarnings("unchecked")
@Override
public JSONObject extract() {
public JSONObject extract(boolean skipSensitive) {
JSONObject result = new JSONObject();
result.put(VERSION, version);
result.put(REVISION, revision);

View File

@ -64,11 +64,11 @@ public final class FormSerialization {
* @return JSON object with serialized form of the list.
*/
@SuppressWarnings("unchecked")
public static JSONArray extractForms(List<MForm> mForms) {
public static JSONArray extractForms(List<MForm> mForms, boolean skipSensitive) {
JSONArray forms = new JSONArray();
for (MForm mForm : mForms) {
forms.add(extractForm(mForm));
forms.add(extractForm(mForm, skipSensitive));
}
return forms;
@ -78,10 +78,11 @@ public static JSONArray extractForms(List<MForm> mForms) {
* Transform given form to JSON Object.
*
* @param mForm Given MForm instance
* @param skipSensitive conditionally add sensitive input values
* @return Serialized JSON object.
*/
@SuppressWarnings("unchecked")
public static JSONObject extractForm(MForm mForm) {
public static JSONObject extractForm(MForm mForm, boolean skipSensitive) {
JSONObject form = new JSONObject();
form.put(ID, mForm.getPersistenceId());
form.put(FORM_NAME, mForm.getName());
@ -91,7 +92,6 @@ public static JSONObject extractForm(MForm mForm) {
for (MInput<?> mInput : mForm.getInputs()) {
JSONObject input = new JSONObject();
mInputs.add(input);
input.put(ID, mInput.getPersistenceId());
input.put(FORM_INPUT_NAME, mInput.getName());
input.put(FORM_INPUT_TYPE, mInput.getType().toString());
@ -111,9 +111,12 @@ public static JSONObject extractForm(MForm mForm) {
}
// Serialize value if is there
if(!mInput.isEmpty()) {
// Skip if sensitive
if (!mInput.isEmpty() && !(skipSensitive && ((MStringInput)mInput).isMasked())) {
input.put(FORM_INPUT_VALUE, mInput.getUrlSafeValueString());
}
mInputs.add(input);
}
return form;

View File

@ -20,6 +20,7 @@
import org.apache.sqoop.model.MConnection;
import org.apache.sqoop.model.MStringInput;
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.json.simple.JSONValue;
import org.junit.Test;
@ -49,7 +50,7 @@ public void testSerialization() {
// Serialize it to JSON object
ConnectionBean bean = new ConnectionBean(connection);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();
@ -71,4 +72,47 @@ public void testSerialization() {
.getForms().get(0).getInputs().get(0);
assertEquals("Hi there!", targetInput.getValue());
}
@Test
public void testSensitivityFilter() {
Date created = new Date();
Date updated = new Date();
MConnection connection = getConnection("ahoj");
connection.setName("Connection");
connection.setPersistenceId(666);
connection.setCreationDate(created);
connection.setLastUpdateDate(updated);
// Fill some data at the beginning
MStringInput input = (MStringInput) connection.getConnectorPart().getForms()
.get(0).getInputs().get(0);
input.setValue("Hi there!");
// Serialize it to JSON object
ConnectionBean bean = new ConnectionBean(connection);
JSONObject json = bean.extract(false);
JSONObject jsonFiltered = bean.extract(true);
// Sensitive values should exist
JSONArray all = (JSONArray)json.get("all");
JSONObject allItem = (JSONObject)all.get(0);
JSONArray connectors = (JSONArray)allItem.get("connector");
JSONObject connector = (JSONObject)connectors.get(0);
JSONArray inputs = (JSONArray)connector.get("inputs");
assertEquals(3, inputs.size());
// Inputs are ordered when creating connection
JSONObject password = (JSONObject)inputs.get(2);
assertTrue(password.containsKey("value"));
// Sensitive values should not exist
all = (JSONArray)jsonFiltered.get("all");
allItem = (JSONObject)all.get(0);
connectors = (JSONArray)allItem.get("connector");
connector = (JSONObject)connectors.get(0);
inputs = (JSONArray)connector.get("inputs");
assertEquals(3, inputs.size());
// Inputs are ordered when creating connection
password = (JSONObject)inputs.get(2);
assertFalse(password.containsKey("value"));
}
}

View File

@ -55,7 +55,7 @@ public void testSerialization() {
// Serialize it to JSON object
ConnectorBean bean = new ConnectorBean(connectors, bundles);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();

View File

@ -44,7 +44,7 @@ public void testSerialization() {
// Serialize it to JSON object
FrameworkBean bean = new FrameworkBean(framework, getResourceBundle());
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();

View File

@ -50,7 +50,7 @@ public void testSerialization() throws ParseException {
// Serialize it to JSON object
JobBean bean = new JobBean(job);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();

View File

@ -158,7 +158,7 @@ public void testTransferCounters() {
*/
private MSubmission transfer(MSubmission submission) {
SubmissionBean bean = new SubmissionBean(submission);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
String string = json.toString();

View File

@ -31,7 +31,7 @@ public void testSerialization() {
// Serialize it to JSON object
ThrowableBean bean = new ThrowableBean(ex);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();

View File

@ -75,10 +75,12 @@ public static MConnectionForms getConnectionForms() {
input = new MStringInput("username", false, (short) 10);
input.setPersistenceId(2);
input.setValue("test");
inputs.add(input);
input = new MStringInput("password", false, (short) 10);
input = new MStringInput("password", true, (short) 10);
input.setPersistenceId(3);
input.setValue("test");
inputs.add(input);
form = new MForm("connection", inputs);

View File

@ -40,7 +40,7 @@ public void testSerialization() {
getValidation(Status.FINE),
getValidation(Status.UNACCEPTABLE)
);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();
@ -78,7 +78,7 @@ public void testId() {
getValidation(Status.FINE)
);
bean.setId((long) 10);
JSONObject json = bean.extract();
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();

View File

@ -108,7 +108,7 @@ private void sendSuccessResponse(RequestContext ctx, JsonBean bean)
response.setStatus(HttpServletResponse.SC_OK);
setContentType(response);
setHeaders(response, SqoopResponseCode.SQOOP_1000);
String responseString = bean.extract().toJSONString();
String responseString = bean.extract(true).toJSONString();
response.getWriter().write(responseString);
response.getWriter().flush();
}
@ -139,7 +139,7 @@ private void sendErrorResponse(RequestContext ctx, Exception ex)
ThrowableBean throwableBean = new ThrowableBean(ex);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(throwableBean.extract().toJSONString());
response.getWriter().write(throwableBean.extract(true).toJSONString());
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}