-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds support for uploading threat intelligence in Custom Format … #1493
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.opensearch.securityanalytics.services; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.opensearch.securityanalytics.commons.connector.codec.InputCodec; | ||
import org.opensearch.securityanalytics.model.STIX2IOC; | ||
import org.opensearch.securityanalytics.threatIntel.model.JsonPathIocSchema; | ||
import org.opensearch.securityanalytics.threatIntel.model.SATIFSourceConfig; | ||
import org.opensearch.securityanalytics.threatIntel.service.JsonPathIocSchemaThreatIntelHandler; | ||
|
||
import java.io.InputStream; | ||
import java.util.List; | ||
import java.util.function.Consumer; | ||
|
||
/** | ||
* An implementation of InputCodec used to parse input stream using JsonPath notations from {@link JsonPathIocSchema} and build a list of {@link STIX2IOC} objects | ||
*/ | ||
public class JsonPathAwareInputCodec implements InputCodec<STIX2IOC> { | ||
private static final Logger logger = LogManager.getLogger(JsonPathAwareInputCodec.class); | ||
private final SATIFSourceConfig satifSourceConfig; | ||
|
||
public JsonPathAwareInputCodec(SATIFSourceConfig satifSourceConfig) { | ||
this.satifSourceConfig = satifSourceConfig; | ||
} | ||
|
||
@Override | ||
public void parse(final InputStream inputStream, final Consumer<STIX2IOC> consumer) { | ||
try { | ||
List<STIX2IOC> stix2IOCS = JsonPathIocSchemaThreatIntelHandler.parseCustomSchema( | ||
(JsonPathIocSchema) satifSourceConfig.getIocSchema(), inputStream, satifSourceConfig.getName(), satifSourceConfig.getId()); | ||
stix2IOCS.forEach(ioc -> { | ||
try { | ||
consumer.accept(ioc); | ||
} catch (Exception e) { | ||
logger.error(String.format("Error while indexing STIX2Ioc - type [%s], value [%s]"), e); | ||
} | ||
}); | ||
} catch (Exception e) { | ||
logger.error(String.format("Error while downloading and indexing STIX2Ioc"), e); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
import org.opensearch.securityanalytics.commons.model.FeedConfiguration; | ||
import org.opensearch.securityanalytics.commons.model.FeedLocation; | ||
import org.opensearch.securityanalytics.commons.model.STIX2; | ||
import org.opensearch.securityanalytics.threatIntel.model.SATIFSourceConfig; | ||
import software.amazon.awssdk.services.s3.S3Client; | ||
|
||
import java.util.List; | ||
|
@@ -35,23 +36,47 @@ public STIX2IOCConnectorFactory(final InputCodecFactory inputCodecFactory, final | |
protected Connector<STIX2> doCreate(FeedConfiguration feedConfiguration) { | ||
final FeedLocation feedLocation = FeedLocation.fromFeedConfiguration(feedConfiguration); | ||
logger.debug("FeedLocation: {}", feedLocation); | ||
switch(feedLocation) { | ||
case S3: return createS3Connector(feedConfiguration); | ||
default: throw new IllegalArgumentException("Unsupported feedLocation: " + feedLocation); | ||
switch (feedLocation) { | ||
case S3: | ||
return createS3Connector(feedConfiguration, null); | ||
default: | ||
throw new IllegalArgumentException("Unsupported feedLocation: " + feedLocation); | ||
} | ||
} | ||
|
||
private S3Connector<STIX2> createS3Connector(final FeedConfiguration feedConfiguration) { | ||
protected Connector<STIX2> doCreate(FeedConfiguration feedConfiguration, SATIFSourceConfig satifSourceConfig) { | ||
final FeedLocation feedLocation = FeedLocation.fromFeedConfiguration(feedConfiguration); | ||
logger.debug("FeedLocation: {}", feedLocation); | ||
switch (feedLocation) { | ||
case S3: | ||
return createS3Connector(feedConfiguration, satifSourceConfig); | ||
default: | ||
throw new IllegalArgumentException("Unsupported feedLocation: " + feedLocation); | ||
} | ||
} | ||
|
||
private S3Connector<STIX2> createS3Connector(final FeedConfiguration feedConfiguration, SATIFSourceConfig satifSourceConfig) { | ||
final InputCodec inputCodec = getInputCodec(feedConfiguration, satifSourceConfig); | ||
final S3ConnectorConfig s3ConnectorConfig = feedConfiguration.getS3ConnectorConfig(); | ||
final S3Client s3Client = s3ClientFactory.create(s3ConnectorConfig.getRoleArn(), s3ConnectorConfig.getRegion()); | ||
final InputCodec inputCodec = inputCodecFactory.create(feedConfiguration.getIocSchema().getModelClass(), feedConfiguration.getInputCodecSchema()); | ||
return new S3Connector<>(s3ConnectorConfig, s3Client, inputCodec); | ||
} | ||
|
||
public S3Connector<STIX2> createAmazonS3Connector(final FeedConfiguration feedConfiguration, List<String> clusterTuple) { | ||
private InputCodec getInputCodec(FeedConfiguration feedConfiguration, SATIFSourceConfig satifSourceConfig) { | ||
final InputCodec inputCodec; | ||
if (satifSourceConfig != null && satifSourceConfig.getIocSchema() != null) { | ||
logger.info("Parsing custom schema JSON from S3 for threat intel source [{}]", satifSourceConfig.getName()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: Would using the source config ID make more sense for this log? Or do we have validation in place to prevent customers from creating configs with the same name? |
||
inputCodec = new JsonPathAwareInputCodec(satifSourceConfig); | ||
} else { | ||
inputCodec = inputCodecFactory.create(feedConfiguration.getIocSchema().getModelClass(), feedConfiguration.getInputCodecSchema()); | ||
} | ||
return inputCodec; | ||
} | ||
|
||
public S3Connector<STIX2> createAmazonS3Connector(final FeedConfiguration feedConfiguration, List<String> clusterTuple, SATIFSourceConfig satifSourceConfig) { | ||
final InputCodec inputCodec = getInputCodec(feedConfiguration, satifSourceConfig); | ||
final S3ConnectorConfig s3ConnectorConfig = feedConfiguration.getS3ConnectorConfig(); | ||
final AmazonS3 s3Client = s3ClientFactory.createAmazonS3(s3ConnectorConfig.getRoleArn(), s3ConnectorConfig.getRegion(), clusterTuple); | ||
final InputCodec inputCodec = inputCodecFactory.create(feedConfiguration.getIocSchema().getModelClass(), feedConfiguration.getInputCodecSchema()); | ||
return new S3Connector<>(s3ConnectorConfig, s3Client, inputCodec); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package org.opensearch.securityanalytics.threatIntel.model; | ||
|
||
import org.opensearch.core.common.io.stream.StreamInput; | ||
import org.opensearch.core.common.io.stream.StreamOutput; | ||
import org.opensearch.core.common.io.stream.Writeable; | ||
import org.opensearch.core.xcontent.ToXContent; | ||
import org.opensearch.core.xcontent.XContentBuilder; | ||
import org.opensearch.core.xcontent.XContentParser; | ||
|
||
import java.io.IOException; | ||
|
||
public class CustomSchemaIocUploadSource extends Source implements Writeable, ToXContent { | ||
public static final String IOCS_FIELD = "iocs"; | ||
public static final String FILE_NAME_FIELD = "file_name"; | ||
private String fileName; | ||
private String iocs; | ||
|
||
public CustomSchemaIocUploadSource(String fileName, String iocs) { | ||
this.fileName = fileName; | ||
this.iocs = iocs; | ||
} | ||
|
||
public CustomSchemaIocUploadSource(StreamInput sin) throws IOException { | ||
this ( | ||
sin.readOptionalString(), // file name | ||
sin.readOptionalString() // iocs | ||
); | ||
} | ||
|
||
public void writeTo(StreamOutput out) throws IOException { | ||
out.writeOptionalString(fileName); | ||
out.writeOptionalString(iocs); | ||
} | ||
|
||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(); | ||
builder.startObject(CUSTOM_SCHEMA_IOC_UPLOAD_FIELD); | ||
if (fileName != null) { | ||
builder.field(FILE_NAME_FIELD, fileName); | ||
} | ||
if(iocs != null) { | ||
builder.field(IOCS_FIELD, iocs); | ||
} | ||
builder.endObject(); | ||
builder.endObject(); | ||
return builder; | ||
} | ||
|
||
@Override | ||
String name() { | ||
return CUSTOM_SCHEMA_IOC_UPLOAD_FIELD; | ||
} | ||
|
||
public static CustomSchemaIocUploadSource parse(XContentParser xcp) throws IOException { | ||
String fileName = null; | ||
String iocs = null; | ||
|
||
while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { | ||
String fieldName = xcp.currentName(); | ||
xcp.nextToken(); | ||
switch (fieldName) { | ||
case FILE_NAME_FIELD: | ||
if (xcp.currentToken() == XContentParser.Token.VALUE_NULL) { | ||
fileName = null; | ||
} else { | ||
fileName = xcp.text(); | ||
} | ||
break; | ||
case IOCS_FIELD: | ||
if (xcp.currentToken() == XContentParser.Token.VALUE_NULL) { | ||
iocs = null; | ||
} else { | ||
iocs = xcp.text(); | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
return new CustomSchemaIocUploadSource(fileName, iocs); | ||
} | ||
|
||
public String getIocs() { | ||
return iocs; | ||
} | ||
|
||
public void setIocs(String iocs) { | ||
this.iocs = iocs; | ||
} | ||
|
||
public String getFileName() { | ||
return fileName; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package org.opensearch.securityanalytics.threatIntel.model; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.opensearch.core.common.io.stream.StreamInput; | ||
import org.opensearch.core.common.io.stream.Writeable; | ||
import org.opensearch.core.xcontent.ToXContentObject; | ||
import org.opensearch.core.xcontent.XContentParser; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken; | ||
|
||
/** | ||
* Stores the schema defined by users who upload threat intelligence in a custom format. | ||
*/ | ||
public abstract class IocSchema<Notation> implements Writeable, ToXContentObject { | ||
private static final Logger log = LogManager.getLogger(IocSchema.class); | ||
abstract String getFormat(); // data format like json, xml, csv etc. | ||
|
||
abstract Notation getId(); | ||
|
||
abstract Notation getName(); | ||
|
||
abstract Notation getType(); | ||
|
||
abstract Notation getValue(); | ||
|
||
abstract Notation getSeverity(); | ||
|
||
abstract Notation getCreated(); | ||
|
||
abstract Notation getModified(); | ||
|
||
abstract Notation getDescription(); | ||
|
||
abstract Notation getLabels(); | ||
|
||
abstract Notation getSpecVersion(); | ||
|
||
static JsonPathIocSchema readFrom(StreamInput sin) throws IOException { | ||
String format = sin.readString(); | ||
switch (format) { | ||
case JsonPathIocSchema.JSON_PATH_DATA_FORMAT: | ||
return new JsonPathIocSchema(sin); | ||
default: | ||
throw new IllegalStateException("Unexpected ioc schema format [" + format + "] found while reading parse stream"); | ||
} | ||
} | ||
|
||
static IocSchema parse(XContentParser xcp) throws IOException { | ||
IocSchema schema = null; | ||
ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp); | ||
while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { | ||
String fieldName = xcp.currentName(); | ||
xcp.nextToken(); | ||
switch (fieldName) { | ||
case JsonPathIocSchema.JSON_PATH_DATA_FORMAT: | ||
schema = JsonPathIocSchema.parse(xcp); | ||
break; | ||
default: | ||
String errorMessage = String.format("Unexpected ioc schema format [%s] found while parsing", fieldName); | ||
log.error(errorMessage); | ||
throw new IllegalStateException(errorMessage); | ||
} | ||
} | ||
return schema; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package org.opensearch.securityanalytics.threatIntel.model; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.opensearch.core.common.io.stream.StreamInput; | ||
import org.opensearch.core.common.io.stream.StreamOutput; | ||
import org.opensearch.core.xcontent.XContentBuilder; | ||
import org.opensearch.core.xcontent.XContentParser; | ||
import org.opensearch.core.xcontent.XContentParserUtils; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* Stores the schema defined by users who upload threat intelligence in a custom format. | ||
* Each field is defined and extracted using {@link com.jayway.jsonpath.JsonPath} annotation. | ||
* Each field is of type {@link JsonPathSchemaField} | ||
*/ | ||
public class JsonPathIocSchema extends IocSchema<JsonPathSchemaField> { | ||
private static final Logger log = LogManager.getLogger(JsonPathIocSchema.class); | ||
public static final String FIELD_ID = "id"; | ||
public static final String FIELD_NAME = "name"; | ||
public static final String FIELD_TYPE = "type"; | ||
public static final String FIELD_VALUE = "value"; | ||
public static final String FIELD_SEVERITY = "severity"; | ||
public static final String FIELD_CREATED = "created"; | ||
public static final String FIELD_MODIFIED = "modified"; | ||
public static final String FIELD_DESCRIPTION = "description"; | ||
public static final String FIELD_LABELS = "labels"; | ||
public static final String FIELD_SPEC_VERSION = "spec_version"; | ||
public static final String JSON_PATH_DATA_FORMAT = "json_path_schema"; | ||
|
||
private final JsonPathSchemaField id; | ||
private final JsonPathSchemaField name; | ||
private final JsonPathSchemaField type; | ||
private final JsonPathSchemaField value; | ||
private final JsonPathSchemaField severity; | ||
private final JsonPathSchemaField created; | ||
private final JsonPathSchemaField modified; | ||
private final JsonPathSchemaField description; | ||
private final JsonPathSchemaField labels; | ||
private final JsonPathSchemaField specVersion; | ||
|
||
public JsonPathIocSchema(JsonPathSchemaField id, JsonPathSchemaField name, JsonPathSchemaField type, JsonPathSchemaField value, JsonPathSchemaField severity, | ||
JsonPathSchemaField created, JsonPathSchemaField modified, JsonPathSchemaField description, JsonPathSchemaField labels, | ||
JsonPathSchemaField specVersion) { | ||
this.id = id; | ||
this.name = name; | ||
this.type = type; | ||
this.value = value; | ||
this.severity = severity; | ||
this.created = created; | ||
this.modified = modified; | ||
this.description = description; | ||
this.labels = labels; | ||
this.specVersion = specVersion; | ||
} | ||
|
||
public JsonPathIocSchema(StreamInput in) throws IOException { | ||
this( | ||
readOptionalSchemaField(in), //id | ||
readOptionalSchemaField(in), //name | ||
readOptionalSchemaField(in), //type | ||
readOptionalSchemaField(in), //value | ||
readOptionalSchemaField(in), //severity | ||
readOptionalSchemaField(in), //created | ||
readOptionalSchemaField(in), //modified | ||
readOptionalSchemaField(in), //description | ||
readOptionalSchemaField(in), //labels | ||
readOptionalSchemaField(in) //specVersion | ||
); | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
writeOptionalSchemaField(id, out); | ||
writeOptionalSchemaField(name, out); | ||
writeOptionalSchemaField(type, out); | ||
writeOptionalSchemaField(value, out); | ||
writeOptionalSchemaField(severity, out); | ||
writeOptionalSchemaField(created, out); | ||
writeOptionalSchemaField(modified, out); | ||
writeOptionalSchemaField(description, out); | ||
writeOptionalSchemaField(labels, out); | ||
writeOptionalSchemaField(specVersion, out); | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(); | ||
builder.startObject(JSON_PATH_DATA_FORMAT); | ||
jsonPathSchemaFieldToXcontent(builder, params, id, FIELD_ID); | ||
jsonPathSchemaFieldToXcontent(builder, params, name, FIELD_NAME); | ||
jsonPathSchemaFieldToXcontent(builder, params, type, FIELD_TYPE); | ||
jsonPathSchemaFieldToXcontent(builder, params, value, FIELD_VALUE); | ||
jsonPathSchemaFieldToXcontent(builder, params, severity, FIELD_SEVERITY); | ||
jsonPathSchemaFieldToXcontent(builder, params, created, FIELD_CREATED); | ||
jsonPathSchemaFieldToXcontent(builder, params, modified, FIELD_MODIFIED); | ||
jsonPathSchemaFieldToXcontent(builder, params, description, FIELD_DESCRIPTION); | ||
jsonPathSchemaFieldToXcontent(builder, params, labels, FIELD_LABELS); | ||
jsonPathSchemaFieldToXcontent(builder, params, specVersion, FIELD_SPEC_VERSION); | ||
builder.endObject(); | ||
return builder.endObject(); | ||
} | ||
|
||
// performs null check before converting to Xcontent | ||
private void jsonPathSchemaFieldToXcontent(XContentBuilder builder, Params params, JsonPathSchemaField jsonPathSchemaField, String fieldName) throws IOException { | ||
if (jsonPathSchemaField != null) { | ||
builder.field(fieldName, jsonPathSchemaField); | ||
} | ||
} | ||
|
||
public static JsonPathIocSchema parse(XContentParser parser) throws IOException { | ||
JsonPathSchemaField idPath = null; | ||
JsonPathSchemaField namePath = null; | ||
JsonPathSchemaField typePath = null; | ||
JsonPathSchemaField valuePath = null; | ||
JsonPathSchemaField severityPath = null; | ||
JsonPathSchemaField createdPath = null; | ||
JsonPathSchemaField modifiedPath = null; | ||
JsonPathSchemaField descriptionPath = null; | ||
JsonPathSchemaField labelsPath = null; | ||
JsonPathSchemaField specVersionPath = null; | ||
|
||
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser); | ||
while (parser.nextToken() != XContentParser.Token.END_OBJECT) { | ||
String fieldName = parser.currentName(); | ||
parser.nextToken(); | ||
|
||
switch (fieldName) { | ||
case FIELD_ID: | ||
idPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_NAME: | ||
namePath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_TYPE: | ||
typePath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_VALUE: | ||
valuePath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_SEVERITY: | ||
severityPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_CREATED: | ||
createdPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_MODIFIED: | ||
modifiedPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_DESCRIPTION: | ||
descriptionPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_LABELS: | ||
labelsPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
case FIELD_SPEC_VERSION: | ||
specVersionPath = JsonPathSchemaField.parse(parser); | ||
break; | ||
default: | ||
parser.skipChildren(); | ||
} | ||
} | ||
|
||
return new JsonPathIocSchema( | ||
idPath, namePath, typePath, valuePath, | ||
severityPath, createdPath, modifiedPath, | ||
descriptionPath, labelsPath, specVersionPath | ||
); | ||
} | ||
|
||
public JsonPathSchemaField getId() { | ||
return id; | ||
} | ||
|
||
public JsonPathSchemaField getName() { | ||
return name; | ||
} | ||
|
||
public JsonPathSchemaField getType() { | ||
return type; | ||
} | ||
|
||
public JsonPathSchemaField getValue() { | ||
return value; | ||
} | ||
|
||
public JsonPathSchemaField getSeverity() { | ||
return severity; | ||
} | ||
|
||
public JsonPathSchemaField getCreated() { | ||
return created; | ||
} | ||
|
||
public JsonPathSchemaField getModified() { | ||
return modified; | ||
} | ||
|
||
public JsonPathSchemaField getDescription() { | ||
return description; | ||
} | ||
|
||
public JsonPathSchemaField getLabels() { | ||
return labels; | ||
} | ||
|
||
public JsonPathSchemaField getSpecVersion() { | ||
return specVersion; | ||
} | ||
|
||
@Override | ||
public String getFormat() { | ||
return JSON_PATH_DATA_FORMAT; | ||
} | ||
|
||
private static void writeOptionalSchemaField(JsonPathSchemaField jsonPathSchemaField, StreamOutput out) throws IOException { | ||
if (jsonPathSchemaField == null) { | ||
out.writeBoolean(false); | ||
} else { | ||
out.writeBoolean(true); | ||
jsonPathSchemaField.writeTo(out); | ||
} | ||
} | ||
|
||
private static JsonPathSchemaField readOptionalSchemaField(StreamInput in) throws IOException { | ||
return in.readBoolean() ? new JsonPathSchemaField(in) : null; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.opensearch.securityanalytics.threatIntel.model; | ||
|
||
import org.opensearch.core.common.io.stream.StreamInput; | ||
import org.opensearch.core.common.io.stream.StreamOutput; | ||
import org.opensearch.core.common.io.stream.Writeable; | ||
import org.opensearch.core.xcontent.ToXContentObject; | ||
import org.opensearch.core.xcontent.XContentBuilder; | ||
import org.opensearch.core.xcontent.XContentParser; | ||
import org.opensearch.core.xcontent.XContentParserUtils; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
* Encapsulates data required to extract value for a field from data based on schema | ||
*/ | ||
public class JsonPathSchemaField implements Writeable, ToXContentObject { | ||
public static final String JSON_PATH_FIELD = "json_path"; | ||
|
||
private final String jsonPath; | ||
|
||
public JsonPathSchemaField(String jsonPath) { | ||
this.jsonPath = jsonPath; | ||
} | ||
|
||
public JsonPathSchemaField(StreamInput in) throws IOException { | ||
this(in.readString()); | ||
} | ||
|
||
public static JsonPathSchemaField parse(XContentParser xcp) throws IOException { | ||
String jsonPath1 = ""; | ||
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp); | ||
while (xcp.nextToken() != XContentParser.Token.END_OBJECT) { | ||
String fieldName = xcp.currentName(); | ||
xcp.nextToken(); | ||
|
||
switch (fieldName) { | ||
case JSON_PATH_FIELD: | ||
jsonPath1 = xcp.text(); | ||
break; | ||
default: | ||
xcp.skipChildren(); | ||
} | ||
} | ||
return new JsonPathSchemaField(jsonPath1); | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
out.writeString(jsonPath); | ||
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | ||
builder.startObject(); | ||
builder.field(JSON_PATH_FIELD, jsonPath); | ||
return builder.endObject(); | ||
} | ||
|
||
public String getJsonPath() { | ||
return jsonPath; | ||
} | ||
} |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious. I noticed that the STIX2IOCDto class is using a
getString
helper function when parsing these fields. Could you clarify why we don't use something similar here?