opentpx 2.2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +15 -0
- data/README.md +44 -0
- data/bin/opentpx_tools +15 -0
- data/lib/tpx.rb +7 -0
- data/lib/tpx/2_2/attribute_accessors.rb +34 -0
- data/lib/tpx/2_2/classification_element.rb +11 -0
- data/lib/tpx/2_2/classification_element_list.rb +11 -0
- data/lib/tpx/2_2/collection.rb +21 -0
- data/lib/tpx/2_2/collection_element.rb +13 -0
- data/lib/tpx/2_2/data_model.rb +32 -0
- data/lib/tpx/2_2/element_observable.rb +41 -0
- data/lib/tpx/2_2/element_observable_list.rb +17 -0
- data/lib/tpx/2_2/exceptions.rb +13 -0
- data/lib/tpx/2_2/exchange.rb +220 -0
- data/lib/tpx/2_2/heterogeneous_list.rb +136 -0
- data/lib/tpx/2_2/homogeneous_list.rb +82 -0
- data/lib/tpx/2_2/mandatory_attributes.rb +69 -0
- data/lib/tpx/2_2/merging_heterogeneous_list.rb +36 -0
- data/lib/tpx/2_2/merging_homogeneous_list.rb +37 -0
- data/lib/tpx/2_2/network.rb +23 -0
- data/lib/tpx/2_2/network_list.rb +11 -0
- data/lib/tpx/2_2/observable.rb +13 -0
- data/lib/tpx/2_2/observable_attribute_map.rb +12 -0
- data/lib/tpx/2_2/observable_definition.rb +15 -0
- data/lib/tpx/2_2/observable_dictionary.rb +12 -0
- data/lib/tpx/2_2/schema/tpx.2.2.schema.json +632 -0
- data/lib/tpx/2_2/threat_observable.rb +14 -0
- data/lib/tpx/2_2/validator.rb +279 -0
- data/lib/tpx/tools.rb +81 -0
- data/lib/tpx/version.rb +3 -0
- data/lib/tpx_2_2.rb +14 -0
- metadata +218 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'tpx/2_2/data_model'
|
2
|
+
require 'tpx/2_2/observable'
|
3
|
+
|
4
|
+
|
5
|
+
module TPX_2_2
|
6
|
+
|
7
|
+
# The representation of the threat observable (the hash map keyed
|
8
|
+
# by the observable_id within the element observable).
|
9
|
+
class ThreatObservable < Observable
|
10
|
+
MANDATORY_ATTRIBUTES = Observable::MANDATORY_ATTRIBUTES + [
|
11
|
+
:occurred_at_t
|
12
|
+
]
|
13
|
+
end # class
|
14
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'deep_merge'
|
2
|
+
# This uses the TPX JSON Schema to validate an input document.
|
3
|
+
module TPX_2_2
|
4
|
+
class Validator
|
5
|
+
|
6
|
+
class << self
|
7
|
+
TPX_KEYS = ['observable_dictionary_c_array', 'element_observable_c_array', 'collection_c_array', 'asn_c_array']
|
8
|
+
MANIFEST_KEYS = ['dictionary_file_manifest', 'observable_element_file_manifest', 'collection_file_manifest', 'network_file_manifest']
|
9
|
+
|
10
|
+
# validate_file! opens json file and validates it. Raises an error if validation fails.
|
11
|
+
#
|
12
|
+
# @param [String] filepath path to file which needs to be validated.
|
13
|
+
# @example
|
14
|
+
# TPX_2_2::Validator.validate_file!('folder_name/file_name.json')
|
15
|
+
def validate_file!(filepath)
|
16
|
+
unless File.exists? filepath
|
17
|
+
raise ValidationError , "No such file or directory '#{filepath}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
@@current_path = File.dirname(filepath)
|
21
|
+
|
22
|
+
begin
|
23
|
+
h = Oj.load_file(filepath)
|
24
|
+
rescue => e
|
25
|
+
raise ValidationError, "File '#{filepath}' is not a valid JSON file:\n#{e}"
|
26
|
+
end
|
27
|
+
|
28
|
+
if h.kind_of?(Hash) and tpx_manifest?(h)
|
29
|
+
DeepMerge::deep_merge!(load_manifest_files(h), h, {:merge_hash_arrays => true})
|
30
|
+
delete_manifest_keys!(h)
|
31
|
+
end
|
32
|
+
|
33
|
+
validate!(h)
|
34
|
+
end
|
35
|
+
|
36
|
+
# validate_json! validates json string. Raises an error if validation fails.
|
37
|
+
#
|
38
|
+
# @param [String] json_enc_str the json string which need to be validated.
|
39
|
+
# @example
|
40
|
+
# TPX_2_2::Validator.validate_json!("{\"provider_s\":\"provider\",\"schema_version_s\":\"2.1.6\",\"source_observable_s\":\"source_observable\",\"source_description_s\":\"source_description\",\"distribution_time_t\":1438862400,\"last_updated_t\":1438862400,\"list_name_s\":\"list_name\",\"element_observable_c_array\":[{\"subject_s\":\"192.168.0.1\",\"type_s\":\"ipv4\",\"score_i\":80,\"score_24hr_decay_i\":0,\"threat_observable_c_map\":{\"Conficker\":{\"occurred_at_t\":4355545,\"last_seen_t\":13123}}}],\"observable_dictionary_c_array\":[{\"observable_id_s\":\"Malicious Host\",\"description_s\":\"This network node is a malicious host.\",\"criticality_i\":20,\"classification_c_array\":[{\"classification_id_s\":\"Malicious Host\",\"criticality_i\":20}]}],\"collection_c_array\":[{\"name_id_s\":\"MarketSeg1\",\"occurred_at_t\":1212312323,\"last_updated_t\":1212312323,\"description_s\":\"This collection is related to MarketSeg1\",\"author_s\":\"Allan Thomson\",\"workspace_s\":\"lg-system\"}],\"asn_c_array\":[{\"asn_number_ui\":1,\"occurred_at_t\":1212312323,\"as_owner_s\":\"ABC Corp\"}]}")
|
41
|
+
def validate_json!(json_enc_str)
|
42
|
+
h = Oj.load(json_enc_str)
|
43
|
+
validate!(h)
|
44
|
+
end
|
45
|
+
|
46
|
+
# validate! validates hash. Raises an error if validation fails.
|
47
|
+
#
|
48
|
+
# @param [Hash] input_hash the hash which needs to be validated.
|
49
|
+
# @example
|
50
|
+
# TPX_2_2::Validator.validate!({
|
51
|
+
# 'provider_s': 'provider',
|
52
|
+
# 'schema_version_s': '2.1.6',
|
53
|
+
# 'source_observable_s': 'source_observable',
|
54
|
+
# 'source_description_s': 'source_description',
|
55
|
+
# 'distribution_time_t': 1438862400,
|
56
|
+
# 'last_updated_t': 1438862400,
|
57
|
+
# 'list_name_s': 'list_name',
|
58
|
+
# 'element_observable_c_array': [
|
59
|
+
# {
|
60
|
+
# 'subject_s': '192.168.0.1',
|
61
|
+
# 'type_s': 'ipv4',
|
62
|
+
# 'score_i': 80,
|
63
|
+
# 'score_24hr_decay_i': 0,
|
64
|
+
# 'threat_observable_c_map': {
|
65
|
+
# 'Conficker': {
|
66
|
+
# 'occurred_at_t': 4355545,
|
67
|
+
# 'last_seen_t': 13123
|
68
|
+
# }
|
69
|
+
# }
|
70
|
+
# }
|
71
|
+
# ],
|
72
|
+
# 'observable_dictionary_c_array': [
|
73
|
+
# {
|
74
|
+
# 'observable_id_s': 'Malicious Host',
|
75
|
+
# 'description_s': 'This network node is a malicious host.',
|
76
|
+
# 'criticality_i': 20,
|
77
|
+
# 'classification_c_array': [
|
78
|
+
# {
|
79
|
+
# 'classification_id_s': 'Malicious Host',
|
80
|
+
# 'criticality_i': 20
|
81
|
+
# }
|
82
|
+
# ]
|
83
|
+
# }
|
84
|
+
# ],
|
85
|
+
# 'collection_c_array': [
|
86
|
+
# {
|
87
|
+
# 'name_id_s': 'MarketSeg1',
|
88
|
+
# 'occurred_at_t': 1212312323,
|
89
|
+
# 'last_updated_t': 1212312323,
|
90
|
+
# 'description_s': 'This collection is related to MarketSeg1',
|
91
|
+
# 'author_s': 'Allan Thomson',
|
92
|
+
# 'workspace_s': 'lg-system'
|
93
|
+
# }
|
94
|
+
# ],
|
95
|
+
# 'asn_c_array': [
|
96
|
+
# {
|
97
|
+
# 'asn_number_ui': 1,
|
98
|
+
# 'occurred_at_t': 1212312323,
|
99
|
+
# 'as_owner_s': 'ABC Corp'
|
100
|
+
# }
|
101
|
+
# ]
|
102
|
+
# })
|
103
|
+
def validate!(input_hash)
|
104
|
+
@@undefined_observables = []
|
105
|
+
|
106
|
+
if input_hash.nil? || input_hash.empty?
|
107
|
+
raise ValidationError, " TPX has no content"
|
108
|
+
end
|
109
|
+
|
110
|
+
validate_schema!(input_hash)
|
111
|
+
|
112
|
+
if (TPX_KEYS & input_hash.keys).length > 0 && tpx_manifest?(input_hash)
|
113
|
+
raise TPX_2_2::ValidationError, "TPX file must either be in single-file or manifest format."
|
114
|
+
end
|
115
|
+
|
116
|
+
validate_element_observables!(input_hash['element_observable_c_array'])
|
117
|
+
validate_observable_dictionary!(input_hash['observable_dictionary_c_array'], input_hash['element_observable_c_array'])
|
118
|
+
validate_collections!(input_hash['collection_c_array'])
|
119
|
+
validate_networks!(input_hash['asn_c_array'])
|
120
|
+
if (input_hash['observable_dictionary_c_array'].nil? || input_hash['observable_dictionary_c_array'].empty?)
|
121
|
+
raise TPX_2_2::ValidationWarning, "observable dictionary is not defined"
|
122
|
+
end
|
123
|
+
unless @@undefined_observables.empty?
|
124
|
+
raise TPX_2_2::ValidationWarning, "observables #{@@undefined_observables.inspect} are not defined in the observable dictionary"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def validate_schema!(input_hash)
|
132
|
+
errors = JSON::Validator.fully_validate(TPX_2_2::SCHEMA, input_hash)
|
133
|
+
raise ValidationError, "#{errors.join(' ')}" unless errors.empty?
|
134
|
+
end
|
135
|
+
|
136
|
+
def validate_element_observables!(element_observable_list)
|
137
|
+
return if element_observable_list.nil? #nothing to validate, just return
|
138
|
+
|
139
|
+
schema = {
|
140
|
+
"type" => "object",
|
141
|
+
"required" => ["threat_observable_c_map"],
|
142
|
+
"properties" => {
|
143
|
+
"threat_observable_c_map" => {"type" => "hash"}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
element_observable_list.each do |element_observable|
|
147
|
+
errors = JSON::Validator.fully_validate(schema, element_observable)
|
148
|
+
raise ValidationError, "#{errors.join(' ')}" unless errors.empty?
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def validate_observable_dictionary!(observable_dictionaries, element_observable_list)
|
153
|
+
return if observable_dictionaries.nil? #nothing to validate, just return
|
154
|
+
|
155
|
+
schema = {
|
156
|
+
"type" => "object",
|
157
|
+
"required" => [
|
158
|
+
"observable_id_s",
|
159
|
+
"description_s",
|
160
|
+
"classification_c_array"
|
161
|
+
],
|
162
|
+
"properties" => {
|
163
|
+
"observable_id_s" => {"type" => "string"},
|
164
|
+
"description_s" => {"type" => "string"},
|
165
|
+
"classification_c_array" => {"type" => "hash"}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
observables = []
|
170
|
+
|
171
|
+
observable_dictionaries.each do |observable_dictionary|
|
172
|
+
errors = JSON::Validator.fully_validate(schema, observable_dictionary)
|
173
|
+
raise TPX_2_2::ValidationError, "#{errors.join(' ')}" unless errors.empty?
|
174
|
+
observables << observable_dictionary['observable_id_s']
|
175
|
+
end
|
176
|
+
|
177
|
+
return if element_observable_list.nil?
|
178
|
+
element_observable_list.each do |element_observable|
|
179
|
+
element = element_observable['threat_observable_c_map'] || element_observable[:threat_observable_c_map]
|
180
|
+
element.each_key do |observable|
|
181
|
+
@@undefined_observables << """#{observable}""" unless observables.include? observable
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
def validate_collections!(collections)
|
188
|
+
return if collections.nil? #nothing to validate, just return
|
189
|
+
|
190
|
+
schema = {
|
191
|
+
"type" => "object",
|
192
|
+
"required" => ["name_id_s"],
|
193
|
+
"properties" => {
|
194
|
+
"name_id_s" => {"type" => "string"}
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
collections.each do |collection|
|
199
|
+
errors = JSON::Validator.fully_validate(schema, collection)
|
200
|
+
raise ValidationError, "#{errors.join(' ')}" unless errors.empty?
|
201
|
+
collection.each do |key, value|
|
202
|
+
if (key == 'collection_c_array') && value.is_a?(Array)
|
203
|
+
validate_collections!(value)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def validate_networks!(networks)
|
210
|
+
return if networks.nil? #nothing to validate, just return
|
211
|
+
|
212
|
+
schema = {
|
213
|
+
"type" => "object",
|
214
|
+
"required" => ["asn_number_ui"],
|
215
|
+
"properties" => {
|
216
|
+
"asn_number_ui" => {"type" => "integer"}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
networks.each do |net|
|
221
|
+
errors = JSON::Validator.fully_validate(schema, net)
|
222
|
+
raise ValidationError, "#{errors.join(' ')}" unless errors.empty?
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# tpx_manifest? returns true if provided hash represents TPX manifest and contains TPX manifest entries
|
227
|
+
#
|
228
|
+
# @param [Hash] Hash with tpx content
|
229
|
+
# @example
|
230
|
+
# TPX_2_2::Validator.tpx_manifest?({ "schema_version_s"=> "2.2.0", "provider_s"=> "Lookingglass Cyber Solutions", "list_name_s"=> "Virus Tracker", "source_observable_s"=> "Virus Tracker", "source_file_s"=> "https://virustracker.net/", "source_description_s"=> "Virus Tracker provides real-time information about virus infections observed through custom sinkholes.", "distribution_time_t"=> 1443007504, "last_updated_t"=> 1443007504, "score_i"=> 90, "dictionary_file_manifest"=> [ "dictionary.json" ], "observable_element_file_manifest"=> [ "data8.json" ]})
|
231
|
+
def tpx_manifest?(input_hash)
|
232
|
+
(MANIFEST_KEYS & input_hash.keys).length > 0
|
233
|
+
end
|
234
|
+
|
235
|
+
# current_path returns the current path which can be one of: 1) current working directory 2) file directory path being validated
|
236
|
+
def current_path
|
237
|
+
@@current_path || Dir.pwd
|
238
|
+
end
|
239
|
+
|
240
|
+
# load_manifest_files loads files referenced in manifests and returns merged content
|
241
|
+
#
|
242
|
+
# @param [Hash] Hash with tpx content
|
243
|
+
def load_manifest_files(input_hash)
|
244
|
+
res = {}
|
245
|
+
MANIFEST_KEYS.each do |manifest_section|
|
246
|
+
files = input_hash[manifest_section]
|
247
|
+
unless files.blank?
|
248
|
+
files.each do |manifest_file|
|
249
|
+
DeepMerge::deep_merge!(load_manifest_file(manifest_file), res, {:merge_hash_arrays => true})
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
res
|
254
|
+
end
|
255
|
+
|
256
|
+
# delete_manifest_keys! deletes manifest keys from input_hash in order to be valid TPX
|
257
|
+
#
|
258
|
+
# @param [Hash] Hash with tpx content
|
259
|
+
def delete_manifest_keys!(input_hash)
|
260
|
+
MANIFEST_KEYS.each do |key|
|
261
|
+
input_hash.delete key
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# load_manifest_file loads TPX content from specified file, in case if file doesn't exists searches for it in current_path. In case if file not found ValidationError is raised
|
266
|
+
#
|
267
|
+
# @param [String] filename
|
268
|
+
def load_manifest_file(filename)
|
269
|
+
return Oj.load_file(filename) if File.exists? filename
|
270
|
+
|
271
|
+
filepath = File.join(current_path, File.basename(filename))
|
272
|
+
return Oj.load_file(filepath) if File.exists? filepath
|
273
|
+
|
274
|
+
raise ValidationError, "Could not find #{filename}"
|
275
|
+
end
|
276
|
+
|
277
|
+
end # class < self
|
278
|
+
end
|
279
|
+
end
|
data/lib/tpx/tools.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require 'tpx'
|
3
|
+
|
4
|
+
module TPX
|
5
|
+
class Tools
|
6
|
+
extend ::GLI::App
|
7
|
+
|
8
|
+
TPX_VALID = "Validation succeeded"
|
9
|
+
TPX_INVALID = "The TPX file provided is invalid for the following reasons:"
|
10
|
+
TPX_VERSION_UNKNOWN = "Unknown TPX Version: "
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :quiet
|
14
|
+
|
15
|
+
def msg(message)
|
16
|
+
puts message unless quiet
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_tpx_version_const(tpx_version)
|
20
|
+
underscored_tpx_version = tpx_version.gsub('.', '_')
|
21
|
+
Object.const_get("TPX_#{underscored_tpx_version}")
|
22
|
+
rescue NameError => e
|
23
|
+
msg( e )
|
24
|
+
raise TPX_VERSION_UNKNOWN + "'#{tpx_version}'"
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate(tpx_version_const, filepath)
|
28
|
+
begin
|
29
|
+
tpx_version_const::Validator.validate_file! filepath
|
30
|
+
rescue tpx_version_const::ValidationWarning => w
|
31
|
+
msg( "Warning: #{w}" )
|
32
|
+
puts TPX_VALID + " against " + tpx_version_const.to_s
|
33
|
+
rescue => e
|
34
|
+
puts TPX_INVALID
|
35
|
+
puts e
|
36
|
+
else
|
37
|
+
puts TPX_VALID
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
program_desc 'OpenTPX Tools'
|
45
|
+
version TPX::VERSION
|
46
|
+
|
47
|
+
switch [:q, :quiet], default_value: false,
|
48
|
+
desc: 'quiet non-essential output and warnings.'
|
49
|
+
|
50
|
+
#--- COMMAND validate
|
51
|
+
desc "validates that a file is of a valid TPX file format"
|
52
|
+
long_desc "validates that a file is of a valid TPX file format\n\n" \
|
53
|
+
"TPX_FILE_PATH - The path to the TPX file. The file may be either a" \
|
54
|
+
" stand-alone TPX file or a tpx manifest file. For details on TPX" \
|
55
|
+
" manifest, please see https://github.com/Lookingglass/tpx"
|
56
|
+
|
57
|
+
arg 'TPX_FILE_PATH'
|
58
|
+
|
59
|
+
command :validate do |c|
|
60
|
+
c.flag [:v, :tpx_version], default_value: "2.2",
|
61
|
+
arg_name: 'VERSION',
|
62
|
+
type: String,
|
63
|
+
desc: "The version of tpx to validate the file against. Possible" \
|
64
|
+
" values: '2.2'"
|
65
|
+
|
66
|
+
c.action do |global_options, options, args|
|
67
|
+
self.quiet = global_options[:quiet]
|
68
|
+
tpx_version = options[:tpx_version]
|
69
|
+
tpx_file_path = args[0]
|
70
|
+
|
71
|
+
raise "Missing option TPX_VERSION" if tpx_version.nil?
|
72
|
+
raise "Missing arg TPX_FILE_PATH" if tpx_file_path.nil?
|
73
|
+
|
74
|
+
tpx_version = tpx_version.strip
|
75
|
+
msg( "Validating '#{tpx_file_path}' against TPX '#{tpx_version}' schema" )
|
76
|
+
tpx_version_const = get_tpx_version_const(tpx_version)
|
77
|
+
validate(tpx_version_const, tpx_file_path)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/tpx/version.rb
ADDED
data/lib/tpx_2_2.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module TPX_2_2
|
2
|
+
CURRENT_SCHEMA_VERSION = '2.2.0'
|
3
|
+
SCHEMA = File.join(File.dirname(File.expand_path(__FILE__)), 'tpx', '2_2', 'schema', 'tpx.2.2.schema.json')
|
4
|
+
|
5
|
+
require 'json-schema'
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/core_ext/object/blank'
|
8
|
+
require 'active_support/core_ext/hash'
|
9
|
+
require 'oj'
|
10
|
+
|
11
|
+
require 'tpx/2_2/exceptions'
|
12
|
+
require 'tpx/2_2/validator'
|
13
|
+
require 'tpx/2_2/exchange'
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opentpx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.0.17
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- LookingGlass
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: timecop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: oj
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: json-schema
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.5.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.5.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: deep_merge
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: gli
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 2.13.2
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 2.13.2
|
153
|
+
description: An open-source format and tools for exchanging threat intelligence data. This
|
154
|
+
is a JSON-based format that allows sharing of data between partner organizations.
|
155
|
+
email:
|
156
|
+
- support@lgscout.com
|
157
|
+
executables:
|
158
|
+
- opentpx_tools
|
159
|
+
extensions: []
|
160
|
+
extra_rdoc_files: []
|
161
|
+
files:
|
162
|
+
- LICENSE.txt
|
163
|
+
- README.md
|
164
|
+
- bin/opentpx_tools
|
165
|
+
- lib/tpx.rb
|
166
|
+
- lib/tpx/2_2/attribute_accessors.rb
|
167
|
+
- lib/tpx/2_2/classification_element.rb
|
168
|
+
- lib/tpx/2_2/classification_element_list.rb
|
169
|
+
- lib/tpx/2_2/collection.rb
|
170
|
+
- lib/tpx/2_2/collection_element.rb
|
171
|
+
- lib/tpx/2_2/data_model.rb
|
172
|
+
- lib/tpx/2_2/element_observable.rb
|
173
|
+
- lib/tpx/2_2/element_observable_list.rb
|
174
|
+
- lib/tpx/2_2/exceptions.rb
|
175
|
+
- lib/tpx/2_2/exchange.rb
|
176
|
+
- lib/tpx/2_2/heterogeneous_list.rb
|
177
|
+
- lib/tpx/2_2/homogeneous_list.rb
|
178
|
+
- lib/tpx/2_2/mandatory_attributes.rb
|
179
|
+
- lib/tpx/2_2/merging_heterogeneous_list.rb
|
180
|
+
- lib/tpx/2_2/merging_homogeneous_list.rb
|
181
|
+
- lib/tpx/2_2/network.rb
|
182
|
+
- lib/tpx/2_2/network_list.rb
|
183
|
+
- lib/tpx/2_2/observable.rb
|
184
|
+
- lib/tpx/2_2/observable_attribute_map.rb
|
185
|
+
- lib/tpx/2_2/observable_definition.rb
|
186
|
+
- lib/tpx/2_2/observable_dictionary.rb
|
187
|
+
- lib/tpx/2_2/schema/tpx.2.2.schema.json
|
188
|
+
- lib/tpx/2_2/threat_observable.rb
|
189
|
+
- lib/tpx/2_2/validator.rb
|
190
|
+
- lib/tpx/tools.rb
|
191
|
+
- lib/tpx/version.rb
|
192
|
+
- lib/tpx_2_2.rb
|
193
|
+
homepage: http://www.opentpx.org
|
194
|
+
licenses:
|
195
|
+
- The Apache License, Version 2.0. See LICENSE.txt
|
196
|
+
metadata: {}
|
197
|
+
post_install_message:
|
198
|
+
rdoc_options: []
|
199
|
+
require_paths:
|
200
|
+
- lib
|
201
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - ">="
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
211
|
+
requirements: []
|
212
|
+
rubyforge_project:
|
213
|
+
rubygems_version: 2.4.3
|
214
|
+
signing_key:
|
215
|
+
specification_version: 4
|
216
|
+
summary: Open Threat Partner Exchange (OpenTPX)
|
217
|
+
test_files: []
|
218
|
+
has_rdoc:
|