1# Copyright (c) 2017, The MITRE Corporation. All rights reserved.
2# See LICENSE.txt for complete terms.
3
4import copy
5import unittest
6
7from mixbox.vendor.six import BytesIO
8
9from stix.test import EntityTestCase, assert_warnings
10from stix.test import report_test
11from stix.test.common import kill_chains_test, related_test
12
13from . import stix_header_test
14
15from stix import core, report
16from stix.core import stix_package
17from stix.campaign import Campaign
18from stix.coa import CourseOfAction
19from stix.exploit_target import ExploitTarget
20from stix.indicator import Indicator
21from stix.incident import Incident
22from stix.threat_actor import ThreatActor
23from stix.ttp import TTP
24from stix.utils import silence_warnings, now
25
26
27class CampaignsTests(EntityTestCase, unittest.TestCase):
28    klass = stix_package.Campaigns
29
30    _full_dict = [
31        {'idref': 'example:test-1'}
32    ]
33
34
35class COAsTests(EntityTestCase, unittest.TestCase):
36    klass = stix_package.CoursesOfAction
37
38    _full_dict = [
39        {'idref': 'example:test-1'}
40    ]
41
42
43class ExploitTargetsTests(EntityTestCase, unittest.TestCase):
44    klass = stix_package.ExploitTargets
45
46    _full_dict = [
47        {'idref': 'example:test-1'}
48    ]
49
50
51class IncidentsTests(EntityTestCase, unittest.TestCase):
52    klass = stix_package.Incidents
53
54    _full_dict = [
55        {'idref': 'example:test-1'}
56    ]
57
58
59class IndicatorsTests(EntityTestCase, unittest.TestCase):
60    klass = stix_package.Indicators
61
62    _full_dict = [
63        {'idref': 'example:test-1'}
64    ]
65
66
67class ThreatActorsTests(EntityTestCase, unittest.TestCase):
68    klass = stix_package.ThreatActors
69
70    _full_dict = [
71        {'idref': 'example:test-1'}
72    ]
73
74
75class TTPsTests(EntityTestCase, unittest.TestCase):
76    klass = stix_package.TTPs
77
78    _full_dict = {
79        'kill_chains': kill_chains_test.KillChainsTests._full_dict,
80        'ttps': [
81            {'idref': 'example:test-1'}
82        ]
83    }
84
85
86class ReportsTests(EntityTestCase, unittest.TestCase):
87    klass = stix_package.Reports
88
89    _full_dict = [
90        report_test.ReportTests._full_dict
91    ]
92
93
94class STIXPackageTests(EntityTestCase, unittest.TestCase):
95    klass = core.STIXPackage
96    _full_dict = {
97        'stix_header': stix_header_test.STIXHeaderTests._full_dict,
98        'campaigns': CampaignsTests._full_dict,
99        'courses_of_action': COAsTests._full_dict,
100        'exploit_targets': ExploitTargetsTests._full_dict,
101        'incidents': IncidentsTests._full_dict,
102        'indicators': IndicatorsTests._full_dict,
103        'observables':  {
104            'cybox_major_version': '2',
105            'cybox_minor_version': '1',
106            'cybox_update_version': '0',
107            'observables': [
108                {
109                    'idref': "example:Observable-1"
110                }
111            ]
112        },
113        'threat_actors': ThreatActorsTests._full_dict,
114        'ttps': TTPsTests._full_dict,
115        'related_packages': related_test.RelatedPackagesTests._full_dict,
116        'reports': ReportsTests._full_dict,
117        'version': "1.2"
118    }
119
120
121    @silence_warnings
122    def test_deepcopy(self):
123        """Test copy.deepcopy() against parsed document.
124
125        Previous versions of python-stix would cause an exception with
126        copy.deepcopy() when applied to a parsed STIX component which contained
127        timestamp information.
128
129        This was due to the lack of a __reduce__ function defined on the
130        bindings._FixedTZOffset class.
131
132        """
133        package = core.STIXPackage.from_xml(
134            BytesIO(
135                core.STIXPackage().to_xml()
136            )
137        )
138
139        copied = copy.deepcopy(package)
140        self.assertEqual(package.timestamp, copied.timestamp)
141
142    @assert_warnings
143    def test_deprecated_idref(self):
144        p = core.STIXPackage()
145        p.idref = "test"
146        self.assertEqual(p.idref, "test")
147
148    @assert_warnings
149    def test_deprecated_timestamp(self):
150        p = core.STIXPackage()
151        ts = now()
152        p.timestamp = ts
153        self.assertEqual(ts, p.timestamp)
154
155    @assert_warnings
156    def test_campaign_idref_deprecation(self):
157        package = core.STIXPackage()
158        package.add(Campaign(idref='test-idref-dep'))
159
160    @assert_warnings
161    def test_coa_idref_deprecation(self):
162        package = core.STIXPackage()
163        package.add(CourseOfAction(idref='test-idref-dep'))
164
165    @assert_warnings
166    def test_et_idref_deprecation(self):
167        package = core.STIXPackage()
168        package.add(ExploitTarget(idref='test-idref-dep'))
169
170    @assert_warnings
171    def test_incident_idref_deprecation(self):
172        package = core.STIXPackage()
173        package.add(Incident(idref='test-idref-dep'))
174
175    @assert_warnings
176    def test_indicator_idref_deprecation(self):
177        package = core.STIXPackage()
178        package.add(Indicator(idref='test-idref-dep'))
179
180    @assert_warnings
181    def test_ta_idref_deprecation(self):
182        package = core.STIXPackage()
183        package.add(ThreatActor(idref='test-idref-dep'))
184
185    @assert_warnings
186    def test_ttp_idref_deprecation(self):
187        package = core.STIXPackage()
188        package.add(TTP(idref='test-idref-dep'))
189
190    @assert_warnings
191    def test_related_package_idref_deprecation(self):
192        package = core.STIXPackage()
193        package.add_related_package(core.STIXPackage(idref='foo'))
194
195    def test_setting_report_ttps_fails_on_stix_package(self):
196        self.assertRaises(TypeError, core.STIXPackage(), report.TTPs(), 'TTPs must be a <class \'stix.core.ttps.TTPs\'>, not a <class \'stix.report.TTPs\'>')
197
198
199if __name__ == "__main__":
200    unittest.main()
201