Skip to content

Commit

Permalink
Add End to End Unit Testing for JSON De/Serialization (#79)
Browse files Browse the repository at this point in the history
* update names of mock methods

* fix naming of json annotations for proper updates

* Updates to support proper sequence generation

* add printing of object and json outputs for manual review and update test description

* adds support for IdentitySDO

* add identity SDO testing support

* Add random label generator

* Add support for Campaign SDO

* remove tabs

* Add course of action, intrusion set tests + fixes to related SDOs + cleanup

* add Malware, ObservedData + Artifact + Fix for hashes pluralization

* remove old imports

* Fix misnamed method

* Add Autonomous System COO

* Add DirectoryCOO

* Add Domain Name COO

* Add Email Address COO

* removing inner Set<String> from headers to conform to spec, even though its a issue

The spec dictates this is a "Dictionary" field.  But a dictionary cannot have duplicate fields.  oasis-tcs/cti-stix2#138

* Add Email Message COO + MimePartType which is used in email message

* Fix bad business rule for email message

* add comment

* fix bad naming of jsonpropertydescription

* Add dupluralizeDictionary values for better method naming

* reorder methods to match the ordering in the spec

* Add support for File Coo

* Cleanup on COO Extension serializer and deserializer for better output

* Remove unneeded Annotations as the MimePartType only exists as a sub object and has not "typing"

* Add Valid annotation to getBodyMultipart so the MimePartTypeObj is validated against the EmailMessage validation

* cleanup + fix file coo issues

* add missing GenericValdiation extends on COO inner types

* Remove valid anotation as it will be handled by the GenericValidation interface of MimePartTypeObj

* convert list mocking to use fromStrings() method provided by mockneat

* remove old code for better Mimes dictionary

* adjust default range for sector generation in identites

* change custom props to generate with prepend

* fix regression with threat actor sdo

* Add IVP4 COO supporte

* Add IPV6 COO support

* Add Mac Address COO + MacAddress generation support on IVP4 and IPV6 COO

* fix types

* Add Mutex and NetworkTraffic COO

* Fix type in method name

* Add Process COO support

* Remove regex until better working pattern can be created

* Add Software COO

* Add URL coo

* fix vocab placement

* Add UserAccount COO and cleanup

* Add user account coo to Observed Object generator

* fix vocab annotation placement

* cleanup todo

* Add Windows Registry Key Coo support

* Fix network traffic annotations for range

* fix regex pattern annotaiton placement

* Cleanup to fix bugs

* Cleanup + Add depluralize dictionary support

* Add X509 cert COO support

* Add TheatActor, Report, Tool, Vulnerability SDO support plus cleanup

* Add alias/aliases dictionary for depluralization of methods

* Fix annotation for vocab on labels

* Fix business rule that was using incorrect methods (isEmpty vs isPresent)

* Add jsonassert

* Update attack pattern with use of objectmapper and json assert

* Update for using ObjectMapper for serialization/deserialization within specs

* cleanup imports

* remove unneeded imports from groovy.json

* Remove unneeded Style annotation

* Add custom properties support onto the Bundle object

* Add mock bundle support

* Remove old tests that are not needed

* remove old json files from tests

* refactor and add readme context for test resources

* refactor mockDatagenerator groovy trait location

* Add custom props support to Marking Objects and Granular Marking Objects

* fix javadoc

* Add Granular Marking, Object Marking, Statement and TLP support + updated all SDOs with CreatedByRef + Updated Report and Bundle to generate Object Markings

* remove markovs are they are way too slow!

* rename method for clearner usage

* Add Markings Definition support + JsontypeName support for TLP and Statement Markings

* refactor vocabularies into clearner packages

* update deps and add missing imports for refactor of vocabs packages

* Add Relationship and Sighting SROs support.  Added to Bundle and Report + Add individual Spec tests
  • Loading branch information
StephenOTT authored Feb 18, 2019
1 parent d9c98ec commit 8f7a602
Show file tree
Hide file tree
Showing 110 changed files with 3,230 additions and 977 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.5.0</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/io/digitalstate/stix/bundle/BundleObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.digitalstate.stix.common.StixCustomProperties;
import io.digitalstate.stix.helpers.StixSpecVersion;
import io.digitalstate.stix.json.StixParsers;
import io.digitalstate.stix.validation.GenericValidation;
Expand Down Expand Up @@ -34,7 +35,7 @@
@Value.Style(typeImmutable = "Bundle", validationMethod = Value.Style.ValidationMethod.NONE, additionalJsonAnnotations = {JsonTypeName.class}, depluralize = true)
@JsonSerialize(as = Bundle.class) @JsonDeserialize(builder = Bundle.Builder.class)
@JsonPropertyOrder({"type", "id", "spec_version", "objects"})
public interface BundleObject extends GenericValidation, Serializable {
public interface BundleObject extends GenericValidation, Serializable, StixCustomProperties {

@NotBlank
@JsonProperty("type")
Expand Down Expand Up @@ -67,6 +68,7 @@ default String getSpecVersion() {
default String toJsonString() {
JsonNode response = StixParsers.getJsonMapper(true).valueToTree(this);
ObjectNode responseNode = (ObjectNode) response;
//@TODO Refactor as this is causing custom properties to come before the Objects prop:
responseNode.putArray("objects");
ArrayNode objects = (ArrayNode) response.get("objects");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import io.digitalstate.stix.validation.contraints.startswith.StartsWith;
import org.hibernate.validator.constraints.Length;
import org.immutables.value.Value;

import java.util.Map;

/**
* Stix Custom Properties
*/

@Value.Style(validationMethod = Value.Style.ValidationMethod.NONE)
public interface StixCustomProperties {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import io.digitalstate.stix.validation.contraints.defaulttypevalue.DefaultTypeValue;
import io.digitalstate.stix.validation.contraints.vocab.Vocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.NetworkSocketAddressFamilies;
import io.digitalstate.stix.vocabularies.NetworkSocketProtocolFamilies;
import io.digitalstate.stix.vocabularies.NetworkSocketTypes;
import io.digitalstate.stix.vocabulary.vocabularies.NetworkSocketAddressFamilies;
import io.digitalstate.stix.vocabulary.vocabularies.NetworkSocketProtocolFamilies;
import io.digitalstate.stix.vocabulary.vocabularies.NetworkSocketTypes;
import org.immutables.serial.Serial;
import org.immutables.value.Value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import io.digitalstate.stix.validation.contraints.hashingvocab.HashingVocab;
import io.digitalstate.stix.validation.contraints.vocab.Vocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.HashingAlgorithms;
import io.digitalstate.stix.vocabularies.WindowsPeBinaryTypes;
import io.digitalstate.stix.vocabulary.vocabularies.HashingAlgorithms;
import io.digitalstate.stix.vocabulary.vocabularies.WindowsPeBinaryTypes;
import org.hibernate.validator.constraints.Length;
import org.immutables.serial.Serial;
import org.immutables.value.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import io.digitalstate.stix.validation.contraints.defaulttypevalue.DefaultTypeValue;
import io.digitalstate.stix.validation.contraints.vocab.Vocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.WindowsServiceStartTypes;
import io.digitalstate.stix.vocabularies.WindowsServiceStatuses;
import io.digitalstate.stix.vocabularies.WindowsServiceTypes;
import io.digitalstate.stix.vocabulary.vocabularies.WindowsServiceStartTypes;
import io.digitalstate.stix.vocabulary.vocabularies.WindowsServiceStatuses;
import io.digitalstate.stix.vocabulary.vocabularies.WindowsServiceTypes;
import org.immutables.serial.Serial;
import org.immutables.value.Value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public Set<CyberObservableExtension> deserialize(JsonParser p, DeserializationCo
CyberObservableExtension extension = node.traverse(p.getCodec()).readValueAs(CyberObservableExtension.class);
extensions.add(extension);
} catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException("Cannot deserialize COO extension: ", e);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Set<CyberObservableObject> deserialize(JsonParser p, DeserializationConte
tree.fieldNames().forEachRemaining(f->{
ObjectNode node = (ObjectNode)tree.get(f);
node.put("observable_object_key", f);
System.out.println(node.toString());
// System.out.println(node.toString());
try {
CyberObservableObject object = node.traverse(p.getCodec())
.readValueAs(CyberObservableObject.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import io.digitalstate.stix.validation.contraints.defaulttypevalue.DefaultTypeValue;
import io.digitalstate.stix.validation.contraints.hashingvocab.HashingVocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.HashingAlgorithms;
import io.digitalstate.stix.vocabulary.vocabularies.HashingAlgorithms;
import org.hibernate.validator.constraints.Length;
import org.immutables.serial.Serial;
import org.immutables.value.Value;
Expand All @@ -27,7 +27,7 @@
*/
@Value.Immutable @Serial.Version(1L)
@DefaultTypeValue(value = "artifact", groups = {DefaultValuesProcessor.class})
@Value.Style(typeAbstract="*Coo", typeImmutable="*", validationMethod = Value.Style.ValidationMethod.NONE, additionalJsonAnnotations = {JsonTypeName.class}, depluralize = true)
@Value.Style(typeAbstract="*Coo", typeImmutable="*", validationMethod = Value.Style.ValidationMethod.NONE, additionalJsonAnnotations = {JsonTypeName.class}, depluralize = true, depluralizeDictionary = {"hash:hashes"})
@JsonTypeName("artifact")
@JsonSerialize(as = Artifact.class) @JsonDeserialize(builder = Artifact.Builder.class)
@JsonPropertyOrder({"type", "extensions", "mime_type", "payload_bin", "url", "hashes"})
Expand All @@ -47,8 +47,9 @@ public interface ArtifactCoo extends CyberObservableObject {

@JsonProperty("payload_bin")
@JsonPropertyDescription("Specifies the binary data contained in the artifact as a base64-encoded string.")
Optional<@Pattern(regexp = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$")
String> getPayloadBin();
//Removed the @pattern from within the optional until it is clear on the usage and expectation.
//@Pattern(regexp = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$")
Optional<String> getPayloadBin();

/**
* url-regex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public interface DirectoryCoo extends CyberObservableObject {
@JsonProperty("path_enc")
@JsonPropertyDescription("Specifies the observed encoding for the path.")
Optional<@Pattern(regexp = "^[a-zA-Z0-9/\\.+_:-]{2,250}$")
String> getName();
String> getPathEnc();

@JsonFormat(pattern = StixDataFormats.TIMESTAMP_PATTERN, timezone = "UTC")
@JsonProperty("created")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.immutables.serial.Serial;
import org.immutables.value.Value;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.time.Instant;
import java.util.Map;
Expand All @@ -33,7 +34,7 @@
"received_lines", "additional_header_fields", "body", "body_multipart", "raw_email_ref" })
@JsonInclude(value = NON_EMPTY, content= NON_EMPTY)
@BusinessRule(ifExp = "isMultipart() == true", thenExp = "getBody().isPresent() == false", errorMessage = "Body cannot be used if isMultipart equals true")
@BusinessRule(ifExp = "isMultipart() == false", thenExp = "getBodyMultipart().isPresent() == false", errorMessage = "Body_Multipart cannot be used if isMultipart equals false")
@BusinessRule(ifExp = "isMultipart() == false", thenExp = "getBodyMultipart().isEmpty() == true", errorMessage = "Body_Multipart cannot be used if isMultipart equals false")
public interface EmailMessageCoo extends CyberObservableObject {

@JsonProperty("is_multipart")
Expand Down Expand Up @@ -78,20 +79,22 @@ public interface EmailMessageCoo extends CyberObservableObject {
@JsonPropertyDescription("Specifies one or more Received header fields that may be included in the email headers.")
Set<String> getReceivedLines();

//@TODO Should become a Multi-Map in the future https://github.com/oasis-tcs/cti-stix2/issues/138
@JsonProperty("additional_header_fields")
@JsonPropertyDescription("Specifies any other header fields (except for date, received_lines, content_type, from_ref, sender_ref, to_refs, cc_refs, bcc_refs, and subject) found in the email message, as a dictionary.")
Map<String, Set<String>> getAdditionalHeaderFields();
Map<String, String> getAdditionalHeaderFields();

@JsonProperty("raw_email_ref")
@JsonPropertyDescription("Specifies the raw binary contents of the email message, including both the headers and body, as a reference to an Artifact Object.")
Optional<String> getRawEmailRef();
@JsonProperty("body")
@JsonPropertyDescription("Specifies a string containing the email body.")
Optional<String> getBody();

@JsonProperty("body_multipart")
@JsonPropertyDescription("Specifies a list of the MIME parts that make up the email body.")
Set<MimePartTypeObj> getBodyMultipart();

@JsonProperty("body")
@JsonPropertyDescription("Specifies a string containing the email body.")
Optional<String> getBody();
@JsonProperty("raw_email_ref")
@JsonPropertyDescription("Specifies the raw binary contents of the email message, including both the headers and body, as a reference to an Artifact Object.")
Optional<String> getRawEmailRef();


}
24 changes: 12 additions & 12 deletions src/main/java/io/digitalstate/stix/coo/objects/FileCoo.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import io.digitalstate.stix.validation.contraints.hashingvocab.HashingVocab;
import io.digitalstate.stix.validation.contraints.vocab.Vocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.EncryptionAlgorithms;
import io.digitalstate.stix.vocabularies.HashingAlgorithms;
import io.digitalstate.stix.vocabulary.vocabularies.EncryptionAlgorithms;
import io.digitalstate.stix.vocabulary.vocabularies.HashingAlgorithms;
import org.hibernate.validator.constraints.Length;
import org.immutables.serial.Serial;
import org.immutables.value.Value;
Expand All @@ -34,7 +34,7 @@
*/
@Value.Immutable @Serial.Version(1L)
@DefaultTypeValue(value = "file", groups = {DefaultValuesProcessor.class})
@Value.Style(typeAbstract="*Coo", typeImmutable="*", validationMethod = Value.Style.ValidationMethod.NONE, additionalJsonAnnotations = {JsonTypeName.class}, depluralize = true)
@Value.Style(typeAbstract="*Coo", typeImmutable="*", validationMethod = Value.Style.ValidationMethod.NONE, additionalJsonAnnotations = {JsonTypeName.class}, depluralize = true, depluralizeDictionary = {"hash:hashes"})
@JsonTypeName("file")
@JsonSerialize(as = File.class) @JsonDeserialize(builder = File.Builder.class)
@JsonPropertyOrder({ "type", "extensions", "hashes", "size", "name", "name_enc", "magic_number_hex", "mime_type", "created", "modified",
Expand All @@ -44,7 +44,7 @@
public interface FileCoo extends CyberObservableObject {

@JsonProperty("hashes")
@JsonPropertyDescription("Specifies a dictionary of hashes for the contents of the url or the payload_bin.")
@JsonPropertyDescription("Specifies a dictionary of hashes for the contents of the file.")
Map<@Length(min = 3, max = 256) @HashingVocab(HashingAlgorithms.class) String, String> getHashes();

@JsonProperty("size")
Expand Down Expand Up @@ -90,14 +90,6 @@ public interface FileCoo extends CyberObservableObject {
@JsonPropertyDescription("Specifies the parent directory of the file, as a reference to a Directory Object.")
Optional<String> getParentDirectoryRef();

@JsonProperty("contains_refs")
@JsonPropertyDescription("Specifies a list of references to other Observable Objects contained within the file.")
Set<String> getContainsRefs();

@JsonProperty("content_ref")
@JsonPropertyDescription("Specifies the content of the file, represented as an Artifact Object.")
Optional<String> getContentRef();

@JsonProperty("is_encrypted")
@JsonPropertyDescription("Specifies whether the file is encrypted.")
@NotNull
Expand All @@ -111,4 +103,12 @@ public interface FileCoo extends CyberObservableObject {
@JsonPropertyDescription("Specifies the decryption key used to decrypt the archive file.")
Optional<String> getDecryptionKey();

@JsonProperty("contains_refs")
@JsonPropertyDescription("Specifies a list of references to other Observable Objects contained within the file.")
Set<String> getContainsRefs();

@JsonProperty("content_ref")
@JsonPropertyDescription("Specifies the content of the file, represented as an Artifact Object.")
Optional<String> getContentRef();

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,11 @@ public interface NetworkTrafficCoo extends CyberObservableObject {

@JsonProperty("src_port")
@JsonPropertyDescription("Specifies the source port used in the network traffic, as an integer. The port value MUST be in the range of 0 - 65535.")
@Range(min = 0, max = 65535 )
Optional<Long> getSrcPort();
Optional<@Range(min = 0, max = 65535 ) Integer> getSrcPort();

@JsonProperty("dst_port")
@JsonPropertyDescription("Specifies the destination port used in the network traffic, as an integer. The port value MUST be in the range of 0 - 65535.")
@Range(min = 0, max = 65535)
Optional<Long> getDstPort();
Optional<@Range(min = 0, max = 65535) Integer> getDstPort();

/*
* Specifies the protocols observed in the network traffic, along with their
Expand Down Expand Up @@ -133,7 +131,7 @@ public interface NetworkTrafficCoo extends CyberObservableObject {
*/
@JsonProperty("encapsulates_refs")
@JsonPropertyDescription("Links to other network-traffic objects encapsulated by a network-traffic.")
List<String> getEncapsulatesRefs();
Set<String> getEncapsulatesRefs();

/*
* Must be of type network-traffic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@JsonPropertyOrder({ "type", "extensions", "is_hidden", "pid", "name", "created", "cwd", "arguments", "command_line",
"environment_variables", "opened_connection_refs", "creator_user_ref", "binary_ref", "parent_ref",
"child_refs" })
@BusinessRule(ifExp = "true", thenExp = "getExtensions().isEmpty() == false || isHidden().isPresent() == true || getPid().isPresent() == true || getName().isPresent() == true || getCreated().isPresent() == true || getCwd().isPresent() == true || getArguments().isEmpty() == false || getCommandLine().isPresent() == true ||getEnvironmentVariables().isPresent() == true || getGpenedConnectionRefs().isPresent() == true || getCreatorUserRef().isPresent() == true || getBinaryRef().isPresent() == true || getParentRef().isPresent() == true || getChildRefs().isPresent() == true", errorMessage = "A Process Object MUST contain at least one property (other than type) from this object (or one of its extensions).")
@BusinessRule(ifExp = "true", thenExp = "getExtensions().isEmpty() == false || isHidden().isPresent() == true || getPid().isPresent() == true || getName().isPresent() == true || getCreated().isPresent() == true || getCwd().isPresent() == true || getArguments().isEmpty() == false || getCommandLine().isPresent() == true || getEnvironmentVariables().isEmpty() == false || getOpenedConnectionRefs().isEmpty() == false || getCreatorUserRef().isPresent() == true || getBinaryRef().isPresent() == true || getParentRef().isPresent() == true || getChildRefs().isEmpty == false", errorMessage = "A Process Object MUST contain at least one property (other than type) from this object (or one of its extensions).")
public interface ProcessCoo extends CyberObservableObject {

@JsonProperty("is_hidden")
Expand Down Expand Up @@ -74,7 +74,7 @@ public interface ProcessCoo extends CyberObservableObject {

@JsonProperty("opened_connection_refs")
@JsonPropertyDescription("Specifies the list of network connections opened by the process, as a reference to one or more Network Traffic Objects.")
Set<String> getGpenedConnectionRefs();
Set<String> getOpenedConnectionRefs();

@JsonProperty("creator_user_ref")
@JsonPropertyDescription("Specifies the user that created the process, as a reference to a User Account Object.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ public interface SoftwareCoo extends CyberObservableObject {
* TODO The value for this property MUST be a CPE v2.3 entry from the official NVD CPE Dictionary.
* regex pattern = "^cpe:2\\.3:[aho](?::(?:[a-zA-Z0-9!\"#$%&'()*+,\\\\-_.\/();<=>?@\\[\\]^`{|}~]|\\:)+){10}$"
* Is not valid for the @Pattern annotation (invalid escape chars)
* Remove @Pattern(regexp="^cpe:2\\.3:[aho]") until working solution is provided
*/
@JsonProperty("cpe")
@JsonPropertyDescription("Specifies the Common Platform Enumeration (CPE) entry for the software, if available.")
Optional<@Pattern(regexp="^cpe:2\\.3:[aho]") String> getCpe();
Optional<String> getCpe();

/**
* TODO The value of each list member MUST be an ISO 639-2 language code.
*/
@JsonProperty("languages")
@JsonPropertyDescription("Specifies the languages supported by the software.")
@Pattern(regexp="^[a-z]{3}$")
Set<String> getLanguages();
Set<@Pattern(regexp="^[a-z]{3}$") String> getLanguages();

@JsonProperty("vendor")
@JsonPropertyDescription("Specifies the name of the vendor of the software.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import io.digitalstate.stix.validation.contraints.defaulttypevalue.DefaultTypeValue;
import io.digitalstate.stix.validation.contraints.vocab.Vocab;
import io.digitalstate.stix.validation.groups.DefaultValuesProcessor;
import io.digitalstate.stix.vocabularies.AccountTypes;
import io.digitalstate.stix.vocabulary.vocabularies.AccountTypes;
import org.immutables.serial.Serial;
import org.immutables.value.Value;

Expand Down Expand Up @@ -48,8 +48,7 @@ public interface UserAccountCoo extends CyberObservableObject {

@JsonProperty("account_type")
@JsonPropertyDescription("Specifies the type of the account. This is an open vocabulary and values SHOULD come from the account-type-ov vocabulary.")
@Vocab(AccountTypes.class)
Optional<String> getAccountType();
Optional<@Vocab(AccountTypes.class) String> getAccountType();

@JsonProperty("display_name")
@JsonPropertyDescription("Specifies the display name of the account, to be shown in user interfaces, if applicable.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ public interface WindowsRegistryKeyCoo extends CyberObservableObject {
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern = StixDataFormats.TIMESTAMP_PATTERN, timezone = "UTC")
Optional<Instant> getModified();

/*
* TODO Must be of type user-account
*/
//@TODO Must be of type user-account
@JsonProperty("creator_user_ref")
@JsonPropertyDescription("Specifies a reference to a user account, represented as a User Account Object, that created the registry key.")
Optional<String> getCreatorUserRef();
Expand Down
Loading

0 comments on commit 8f7a602

Please sign in to comment.