Skip to content
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

JSON representation ('value' property) #210

Open
marlontaylor opened this issue Oct 10, 2014 · 2 comments
Open

JSON representation ('value' property) #210

marlontaylor opened this issue Oct 10, 2014 · 2 comments

Comments

@marlontaylor
Copy link

The return type of the 'value' property in the to_dict() varies. ( see AddressObj:AddressObjectType example)

I suggest always returning the array, in these situations.

input.xml

<stix:STIX_Package  xmlns:example_namespace="http://example_namespace"
xmlns:cyboxCommon="http://cybox.mitre.org/common-2" 
xmlns:cybox="http://cybox.mitre.org/cybox-2"
xmlns:cyboxVocabs="http://cybox.mitre.org/default_vocabularies-2"   
xmlns:AddressObj="http://cybox.mitre.org/objects#AddressObject-2"   
xmlns:stixCommon="http://stix.mitre.org/common-1"   
xmlns:stixVocabs="http://stix.mitre.org/default_vocabularies-1" 
xmlns:stix="http://stix.mitre.org/stix-1"   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
xsi:schemaLocation="    http://cybox.mitre.org/common-2 http://cybox.mitre.org/XMLSchema/common/2.1/cybox_common.xsd    http://cybox.mitre.org/cybox-2 http://cybox.mitre.org/XMLSchema/core/2.1/cybox_core.xsd http://cybox.mitre.org/default_vocabularies-2 http://cybox.mitre.org/XMLSchema/default_vocabularies/2.1/cybox_default_vocabularies.xsd  http://cybox.mitre.org/objects#AddressObject-2 http://cybox.mitre.org/XMLSchema/objects/Address/2.1/Address_Object.xsd  http://stix.mitre.org/common-1 http://stix.mitre.org/XMLSchema/common/1.1.1/stix_common.xsd http://stix.mitre.org/default_vocabularies-1 http://stix.mitre.org/XMLSchema/default_vocabularies/1.1.1/stix_default_vocabularies.xsd   http://stix.mitre.org/stix-1 http://stix.mitre.org/XMLSchema/core/1.1.1/stix_core.xsd" version="1.1.1">

  <stix:Observables cybox_major_version="2" cybox_minor_version="1" cybox_update_version="0">
    <cybox:Observable id="example_namespace:Observable-de76dce6-22a9-4709-9924-9eab9b7f531b">
      <cybox:Title>IPs</cybox:Title>
      <cybox:Object id="example_namespace:Object-140d93f8-7bd9-4b23-b3bf-6cc3be8d7b28">
        <cybox:Properties xsi:type="AddressObj:AddressObjectType" category="ipv4-addr">
          <AddressObj:Address_Value condition="Equals" is_case_sensitive="false" apply_condition="ANY" delimiter="##example_namespace##">1.1.1.1##example_namespace##2.2.2.2##example_namespace##3.3.3.3</AddressObj:Address_Value>
        </cybox:Properties>
      </cybox:Object>
    </cybox:Observable>
    <cybox:Observable id="example_namespace:Observable-8442aae7-0a38-4d6e-ae99-12ed42402a22">
      <cybox:Title>ip</cybox:Title>
      <cybox:Object id="example_namespace:Object-dbf87db5-fad7-4492-bf2e-b0a4b82e1d14">
        <cybox:Properties xsi:type="AddressObj:AddressObjectType" category="ipv4-addr">
          <AddressObj:Address_Value condition="Equals" is_case_sensitive="false" apply_condition="ANY" delimiter="##example_namespace##">0.0.0.0</AddressObj:Address_Value>
        </cybox:Properties>
      </cybox:Object>
    </cybox:Observable>
  </stix:Observables>

</stix:STIX_Package>

script.py

#!/usr/bin/env python
# Copyright (c) 2014, The MITRE Corporation. All rights reserved.
# See LICENSE.txt for complete terms.

'''
File: ex_01.py

Description: Round-trip example. This script takes a STIX instance document from XML to
a binding object, then to a api object and then to a dictionary. That dictionary is then
converted back into an api object, which is then used to generate an XML document.
'''

import io
from pprint import pprint

from stix.core import STIXPackage

def main():
   fn = 'input.xml'
   stix_package = STIXPackage.from_xml(fn)
   stix_dict = stix_package.to_dict() # parse to dictionary
   pprint(stix_dict)

   stix_package_two = STIXPackage.from_dict(stix_dict) # create python-stix object from dictionary
   xml = stix_package_two.to_xml() # generate xml from python-stix object
   print(xml)

if __name__ == '__main__':
   main()

output.json

{
    "observables": {
        "observables": [
            {
                "object": {
                    "id": "example_namespace:Object-140d93f8-7bd9-4b23-b3bf-6cc3be8d7b28",
                    "properties": {
                        "category": "ipv4-addr",
                        "xsi:type": "AddressObjectType",
                        "address_value": {
                            "apply_condition": "ANY",
                            "delimiter": "##example_namespace##",
                            "is_case_sensitive": false,
                            "condition": "Equals",
                            "value": [
                                "1.1.1.1",
                                "2.2.2.2",
                                "3.3.3.3"
                            ]
                        }
                    }
                },
                "id": "example_namespace:Observable-de76dce6-22a9-4709-9924-9eab9b7f531b",
                "title": "IPs"
            },
            {
                "object": {
                    "id": "example_namespace:Object-dbf87db5-fad7-4492-bf2e-b0a4b82e1d14",
                    "properties": {
                        "category": "ipv4-addr",
                        "xsi:type": "AddressObjectType",
                        "address_value": {
                            "delimiter": "##example_namespace##",
                            "is_case_sensitive": false,
                            "condition": "Equals",
                            "value": "0.0.0.0"
                        }
                    }
                },
                "id": "example_namespace:Observable-8442aae7-0a38-4d6e-ae99-12ed42402a22",
                "title": "ip"
            }
        ],
        "major_version": 2,
        "update_version": 0,
        "minor_version": 1
    },
    "version": "1.1.1"
}
@bworrell
Copy link
Contributor

@marlontaylor,

The values vary because you aren't always representing a list of values. Sometimes you are passing along a single value. I understand that you are suggesting that we always use lists there, even if that list has a single value, though I'm not sure if there are undesired consequences to changing this.

We can look into doing this on the JSON/dict side of things, but for API object instances, you can use the values property on object fields to always return a list of values (even if there is only one property value).

Python 2.7.8 (default, Jul 28 2014, 01:34:03)
[GCC 4.8.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from cybox.objects.address_object import Address
>>> a = Address()
>>> a.address_value = "10.0.0.0"
>>> a.address_value.value
'10.0.0.0'
>>> a.address_value.values
['10.0.0.0']

@gtback
Copy link
Contributor

gtback commented Oct 15, 2014

I think that always including a list is a bad idea, particularly for CybOX instances, which can never use a list of values. It might be alright to always use them for patterns, but it will still require applications other than python-cybox to do some conditional parsing—python-cybox already takes care of this here.

On a related note, we probably don't need to include the delimiter in the dictionary, since we are using a native JSON list rather than a delimited string. That does mean we need to add some logic to choose a new delimiter if it was deliberately set to allow representing the literal string "##comma##". Right now it just raises a ValueError.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants