Skip to content

Commit

Permalink
feat: request payload converted to json & added json threat protectio…
Browse files Browse the repository at this point in the history
…n policy
  • Loading branch information
payaljindal committed Jan 8, 2024
1 parent dca8b29 commit 4bf4115
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
-->
<AssignMessage name="AM-Set-Json-Response">
<Set>
<Payload contentType="application/json">{
"host":"{request.header.host_name}",
"port": "{request.header.port_number}",
"status":"{flow.reachableStatus}"
}
</Payload>
<Payload contentType="application/json">{flow.result}</Payload>
</Set>
</AssignMessage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JSONThreatProtection continueOnError="false" enabled="true" name="JSON-Threat-Protection">
<DisplayName>JSON Threat Protection</DisplayName>
<Properties/>
<ArrayElementCount>5</ArrayElementCount>
<Source>request</Source>
</JSONThreatProtection>
3 changes: 3 additions & 0 deletions tools/target-server-validator/apiproxy/proxies/default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<ProxyEndpoint name="default">
<PreFlow name="PreFlow">
<Request>
<Step>
<Name>JSON-Threat-Protection</Name>
</Step>
<Step>
<Name>JC-Port-Open-Check</Name>
</Step>
Expand Down
Binary file not shown.
Binary file not shown.
13 changes: 10 additions & 3 deletions tools/target-server-validator/callout/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
<javaxjson.version>1.1.4</javaxjson.version>
<java.version>1.8</java.version>
<apiproxy.java.rsrc.dir>../apiproxy/resources/java</apiproxy.java.rsrc.dir>
<testng.version>6.8.7</testng.version> <!-- current: 6.9.4 -->
<jmockit.version>1.7</jmockit.version>
Expand Down Expand Up @@ -70,6 +71,12 @@ do it manually by running these commands:
<artifactId>expressions</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.json/javax.json-api -->
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1.4</version>
</dependency>

</dependencies>

Expand Down Expand Up @@ -134,7 +141,7 @@ do it manually by running these commands:
<execution>
<phase>package</phase>
<configuration>
<tasks>
<target>
<copy todir="${apiproxy.java.rsrc.dir}">
<fileset dir="${project.build.directory}">
<include name="${project.artifactId}.jar"/>
Expand All @@ -145,7 +152,7 @@ do it manually by running these commands:
</fileset>
<mapper type="flatten"/>
</copy>
</tasks>
</target>
</configuration>
<goals>
<goal>run</goal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.apigee.devrel.apigee_target_server_validator;

import com.google.apigee.json.JavaxJson;
import com.apigee.flow.execution.ExecutionContext;
import com.apigee.flow.execution.ExecutionResult;
import com.apigee.flow.execution.spi.Execution;
Expand All @@ -25,7 +26,13 @@
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import com.apigee.flow.execution.Action;

import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.json.Json;

/**
* A callout that checks if a particular port is open on a specified host.
Expand Down Expand Up @@ -61,7 +68,23 @@ private static String available(final String host, final int port) {
}
}
}
private static String convertMapToJson(Map<String, List<Map<String, String>>> result) {
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();

List<Map<String, String>> listMap = result.get("hostname_portnumbers_status");
for (Map<String, String> map : listMap) {
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
for (Map.Entry<String, String> entry : map.entrySet()) {
jsonObjectBuilder.add(entry.getKey(), entry.getValue());
}
jsonArrayBuilder.add(jsonObjectBuilder);
}

return Json.createObjectBuilder()
.add("hostname_portnumbers_status", jsonArrayBuilder)
.build()
.toString();
}
/**
* Executes the callout.
*
Expand All @@ -72,12 +95,34 @@ private static String available(final String host, final int port) {
public ExecutionResult execute(final MessageContext messageContext,
final ExecutionContext executionContext) {
try {
String hostname = messageContext.getMessage().getHeader("host_name");
String port = messageContext.getMessage().getHeader("port_number");
int portnumber = Integer.parseInt(port);
String status = available(hostname, portnumber);
messageContext.setVariable("flow.reachableStatus", status);
return ExecutionResult.SUCCESS;
String payload = (String) messageContext.getVariable("request.content");
if (payload != null) {
Map<String, List<Map<String, String>>> result = new HashMap<>();
result.put("hostname_portnumbers_status", new ArrayList<>());
Map<String,List<Map<String,String>>> outerMap = JavaxJson.fromJson(payload,Map.class);
for (Map.Entry<String, List<Map<String, String>>> entry : outerMap.entrySet()) {
String hostname_portnumbers = entry.getKey();
List<Map<String, String>> list_map_host_port = entry.getValue();

for (Map<String, String> host_port : list_map_host_port) {
String hostName = (String) host_port.get("host");
String portNumber = (String) host_port.get("port");
Integer portNumberint = Integer.parseInt(portNumber);
String status = available(hostName, portNumberint);
Map<String, String> newEntry = new HashMap<>();
newEntry.put("status",status);
newEntry.putAll(host_port);

result.get("hostname_portnumbers_status").add(newEntry);
}
}
String jsonResult = convertMapToJson(result);
messageContext.setVariable("flow.result", jsonResult);
return ExecutionResult.SUCCESS;
} else {
messageContext.setVariable("ERROR", "set payload");
return ExecutionResult.ABORT;
}
} catch (Exception e) {
ExecutionResult executionResult = new ExecutionResult(false,
Action.ABORT);
Expand All @@ -89,5 +134,5 @@ public ExecutionResult execute(final MessageContext messageContext,
messageContext.setVariable("JAVA_ERROR", e.getMessage());
return executionResult;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// JavaxJson.java

package com.google.apigee.json;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;

public class JavaxJson {
@SuppressWarnings("unchecked")
public static <T> T fromJson(String json, Class<T> beanClass) {
JsonValue value = Json.createReader(new StringReader(json)).read();
return (T) decode(value, beanClass);
}

private static Object decode(JsonValue jsonValue, Type targetType) {
if (jsonValue.getValueType() == ValueType.NULL) {
return null;
} else if (jsonValue.getValueType() == ValueType.TRUE
|| jsonValue.getValueType() == ValueType.FALSE) {
return decodeBoolean(jsonValue, targetType);
} else if (jsonValue instanceof JsonNumber) {
return decodeNumber((JsonNumber) jsonValue, targetType);
} else if (jsonValue instanceof JsonString) {
return decodeString((JsonString) jsonValue, targetType);
} else if (jsonValue instanceof JsonArray) {
return decodeArray((JsonArray) jsonValue, targetType);
} else if (jsonValue instanceof JsonObject) {
return decodeObject((JsonObject) jsonValue, targetType);
} else {
throw new UnsupportedOperationException("Unsupported json value: " + jsonValue);
}
}

private static Object decode(JsonValue jsonValue) {
if (jsonValue.getValueType() == ValueType.NULL) {
return null;
} else if (jsonValue.getValueType() == ValueType.TRUE
|| jsonValue.getValueType() == ValueType.FALSE) {
return decodeBoolean(jsonValue, java.lang.Boolean.class);
} else if (jsonValue instanceof JsonNumber) {
return decodeNumber((JsonNumber) jsonValue, java.lang.Double.class);
} else if (jsonValue instanceof JsonString) {
return decodeString((JsonString) jsonValue, java.lang.String.class);
} else if (jsonValue instanceof JsonArray) {
return decodeArray((JsonArray) jsonValue, java.util.ArrayList.class);
} else if (jsonValue instanceof JsonObject) {
return decodeObject((JsonObject) jsonValue, java.util.Map.class);
} else {
throw new UnsupportedOperationException("Unsupported json value: " + jsonValue);
}
}

private static Object decodeBoolean(JsonValue jsonValue, Type targetType) {
if (targetType == boolean.class || targetType == Boolean.class) {
return Boolean.valueOf(jsonValue.toString());
} else {
throw new UnsupportedOperationException("Unsupported boolean type: " + targetType);
}
}

private static Object decodeNumber(JsonNumber jsonNumber, Type targetType) {
if (targetType == int.class || targetType == Integer.class) {
return jsonNumber.intValue();
} else if (targetType == long.class || targetType == Long.class) {
return jsonNumber.longValue();
} else if (targetType == long.class || targetType == Double.class) {
return jsonNumber.doubleValue();
} else {
throw new UnsupportedOperationException("Unsupported number type: " + targetType);
}
}

private static Object decodeString(JsonString jsonString, Type targetType) {
if (targetType == String.class) {
return jsonString.getString();
} else if (targetType == Date.class) {
try {
return new SimpleDateFormat("MMM dd, yyyy H:mm:ss a", Locale.ENGLISH)
.parse(jsonString.getString()); // This is default Gson format. Alter if necessary.
} catch (ParseException e) {
throw new UnsupportedOperationException(
"Unsupported date format: " + jsonString.getString());
}
} else {
throw new UnsupportedOperationException("Unsupported string type: " + targetType);
}
}

private static Object decodeArray(JsonArray jsonArray, Type targetType) {
boolean isBean = targetType instanceof ParameterizedType;
Class<?> targetClass =
(Class<?>)
((isBean)
? ((ParameterizedType) targetType).getRawType()
: targetType);

if (List.class.isAssignableFrom(targetClass)) {
List<Object> list = new ArrayList<>();
if (isBean) {
Class<?> elementClass =
(Class<?>) ((ParameterizedType) targetType).getActualTypeArguments()[0];

for (JsonValue item : jsonArray) {
list.add(decode(item, elementClass));
}
}
else {
for (JsonValue item : jsonArray) {
list.add(decode(item));
}
}

return list;
} else if (targetClass.isArray()) {
Class<?> elementClass = targetClass.getComponentType();
Object array = Array.newInstance(elementClass, jsonArray.size());

for (int i = 0; i < jsonArray.size(); i++) {
Array.set(array, i, decode(jsonArray.get(i), elementClass));
}

return array;
} else {
throw new UnsupportedOperationException("Unsupported array type: " + targetClass);
}
}

private static Object decodeObject(JsonObject object, Type targetType) {
boolean isBean = targetType instanceof ParameterizedType;
//System.out.printf("\n** is ParameterizedType: %s\n", isBean);

Class<?> targetClass =
(Class<?>) ((isBean) ? ((ParameterizedType) targetType).getRawType() : targetType);

if (Map.class.isAssignableFrom(targetClass)) {
Map<String, Object> map = new LinkedHashMap<>();
if (isBean) {
Class<?> valueClass =
(Class<?>) ((ParameterizedType) targetType).getActualTypeArguments()[1];
for (Map.Entry<String, JsonValue> entry : object.entrySet()) {
map.put(entry.getKey(), decode(entry.getValue(), valueClass));
}
} else {
for (Map.Entry<String, JsonValue> entry : object.entrySet()) {
map.put(entry.getKey(), decode(entry.getValue()));
}
}
return map;
} else
try {
Object bean = targetClass.newInstance();

for (PropertyDescriptor property :
Introspector.getBeanInfo(targetClass).getPropertyDescriptors()) {
if (property.getWriteMethod() != null && object.containsKey(property.getName())) {
property
.getWriteMethod()
.invoke(
bean,
decode(
object.get(property.getName()),
property.getWriteMethod().getGenericParameterTypes()[0]));
}
}

return bean;
} catch (Exception e) {
throw new UnsupportedOperationException("Unsupported object type: " + targetClass, e);
}
}
}

0 comments on commit 4bf4115

Please sign in to comment.