ruby-stix2 0.1.3 → 0.1.4

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +2 -1
  3. data/Gemfile.lock +5 -1
  4. data/README.md +1 -1
  5. data/lib/stix2/bool.rb +5 -0
  6. data/lib/stix2/bundle.rb +1 -1
  7. data/lib/stix2/common.rb +40 -38
  8. data/lib/stix2/custom_object.rb +16 -12
  9. data/lib/stix2/cyberobservable_objects/artifact.rb +12 -1
  10. data/lib/stix2/cyberobservable_objects/email_message.rb +1 -1
  11. data/lib/stix2/cyberobservable_objects/file.rb +12 -1
  12. data/lib/stix2/cyberobservable_objects/ipv4_addr.rb +12 -1
  13. data/lib/stix2/cyberobservable_objects/ipv6_addr.rb +12 -1
  14. data/lib/stix2/cyberobservable_objects/network_traffic.rb +1 -1
  15. data/lib/stix2/cyberobservable_objects/process.rb +1 -1
  16. data/lib/stix2/cyberobservable_objects/user_account.rb +4 -4
  17. data/lib/stix2/cyberobservable_objects/x509_certificate.rb +13 -2
  18. data/lib/stix2/domain_objects/indicator.rb +13 -1
  19. data/lib/stix2/domain_objects/infrastructure.rb +12 -1
  20. data/lib/stix2/domain_objects/intrusion-set.rb +12 -1
  21. data/lib/stix2/domain_objects/malware.rb +31 -5
  22. data/lib/stix2/domain_objects/report.rb +12 -1
  23. data/lib/stix2/domain_objects/threat_actor.rb +30 -4
  24. data/lib/stix2/domain_objects/tool.rb +12 -1
  25. data/lib/stix2/exception.rb +131 -0
  26. data/lib/stix2/extension_definition.rb +12 -1
  27. data/lib/stix2/extensions/alternate_data_stream_type.rb +12 -1
  28. data/lib/stix2/extensions/icmp.rb +18 -2
  29. data/lib/stix2/extensions/pdf.rb +1 -1
  30. data/lib/stix2/extensions/socket.rb +3 -3
  31. data/lib/stix2/extensions/tcp.rb +18 -2
  32. data/lib/stix2/extensions/windows_pe_optional_header_type.rb +48 -7
  33. data/lib/stix2/extensions/windows_pe_section_type.rb +12 -1
  34. data/lib/stix2/extensions/windows_pebinary.rb +30 -4
  35. data/lib/stix2/extensions/windows_process.rb +2 -2
  36. data/lib/stix2/external_reference.rb +12 -1
  37. data/lib/stix2/identifier.rb +2 -2
  38. data/lib/stix2/meta_objects/data_markings/marking_definition.rb +10 -4
  39. data/lib/stix2/meta_objects/data_markings/object_marking.rb +2 -2
  40. data/lib/stix2/meta_objects/language_content.rb +12 -1
  41. data/lib/stix2/relationship_objects/relationship.rb +7 -2
  42. data/lib/stix2/relationship_objects/sighting.rb +1 -1
  43. data/lib/stix2/validators/array.rb +11 -0
  44. data/lib/stix2/validators/hashes.rb +11 -0
  45. data/lib/stix2/validators/hex.rb +10 -0
  46. data/lib/stix2/version.rb +1 -1
  47. data/lib/stix2.rb +8 -10
  48. data/ruby-stix2.gemspec +2 -0
  49. metadata +35 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1325e9bc73496954969bda48fbd2a096c63be31098e6207d72c8260e23a5118f
4
- data.tar.gz: d3e59d85404608530150a0fce245f79a0de28598f0daa14bc68e96c598d623e9
3
+ metadata.gz: 67b0f8e82189d6f2afd28eeb4102d31a43be91ced1e7f465bee8d78d29a12241
4
+ data.tar.gz: 36d6920a1266d271daea0a38279d2236822d44272479cb739d711ed240f95c80
5
5
  SHA512:
6
- metadata.gz: 4fa484ea080ce69d832a71fc45c27dc081385f769895fbbf345ef1eb81109982fa5b1b4bb187b1da6104dc1ee37acf75183164b2b11160609cb607db1c4976d7
7
- data.tar.gz: 68ca00c8308ca9d3fd1b978ecd0525d81f169f4b85d21b03eef9ead386e7f0d4228a594755b442c77ea9c1f6ef1b4bf673c47834e71171fad725853cf30c9dca
6
+ metadata.gz: 5c26a394daae1a60380a6133efe29b1b7129b2c989a8ddc96639fb7059f81af4890551ab2762719c2f9f3a0198cae822b7bbfba8ce76f1a8e5c9d6b30a6abb64
7
+ data.tar.gz: 97d00572bdefaf35f055c5bab2d9840cd2f745a7a5489e11a0c18b793b2af71e320adcc0d4feee31bcef4588f01b067e58e10dd56d999b75fe6cdb5a80f5808a
@@ -9,7 +9,7 @@ jobs:
9
9
  name: Build
10
10
  strategy:
11
11
  matrix:
12
- os: [ubuntu-latest, windows-latest]
12
+ os: [ubuntu-latest, windows-latest, macos-latest]
13
13
  ruby: ['3.0', '3.1', '3.2', '3.3', head]
14
14
  runs-on: ${{ matrix.os }}
15
15
  permissions: write-all
@@ -23,6 +23,7 @@ jobs:
23
23
  - run: bundle
24
24
  - run: bundle exec rake test
25
25
  - run: bundle exec standardrb
26
+ if: ${{ matrix.ruby != 'head' }}
26
27
  - name: SimpleCov Ruby ${{ matrix.ruby }}
27
28
  uses: joshmfrankel/simplecov-check-action@main
28
29
  if: ${{ matrix.os == 'ubuntu-latest' && matrix.ruby == '3.2' }}
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-stix2 (0.1.3)
4
+ ruby-stix2 (0.1.4)
5
5
  hashie (~> 5.0.0)
6
6
 
7
7
  GEM
@@ -18,9 +18,11 @@ GEM
18
18
  json (2.7.2)
19
19
  language_server-protocol (3.17.0.3)
20
20
  lint_roller (1.1.0)
21
+ logger (1.6.5)
21
22
  method_source (1.0.0)
22
23
  minitest (5.18.1)
23
24
  mutex_m (0.2.0)
25
+ ostruct (0.6.1)
24
26
  parallel (1.24.0)
25
27
  parser (3.3.0.5)
26
28
  ast (~> 2.4.1)
@@ -83,8 +85,10 @@ PLATFORMS
83
85
  DEPENDENCIES
84
86
  bundler (~> 2.3)
85
87
  irb (~> 1.7.0)
88
+ logger (~> 1.6.5)
86
89
  minitest (~> 5.18.1)
87
90
  mutex_m (~> 0.2.0)
91
+ ostruct (~> 0.6.1)
88
92
  pry (~> 0.13.0)
89
93
  pry-byebug (~> 3.10.1)
90
94
  rake (~> 13.0)
data/README.md CHANGED
@@ -159,4 +159,4 @@ the development
159
159
 
160
160
  # See also
161
161
 
162
- Ruby Stix2: https://github.com/crondaemon/ruby-taxii2
162
+ Ruby Taxii2: https://github.com/crondaemon/ruby-taxii2
data/lib/stix2/bool.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Stix2
2
+ def self.bool
3
+ ->(value) { (value == true) || (value == "true") }
4
+ end
5
+ end
data/lib/stix2/bundle.rb CHANGED
@@ -3,7 +3,7 @@ module Stix2
3
3
  property :type, required: true, coerce: String
4
4
  property :objects, coerce: ->(array) do
5
5
  array.all? do |element|
6
- element.is_a?(::Stix2::Common) || Stix2.parse(element).is_a?(::Stix2::Common) || raise("Invalid Object")
6
+ element.is_a?(::Stix2::Common) || Stix2.parse(element).is_a?(::Stix2::Common)
7
7
  end && array
8
8
  end
9
9
  end
data/lib/stix2/common.rb CHANGED
@@ -12,36 +12,26 @@ module Stix2
12
12
  property :created_by_ref, coerce: Identifier
13
13
  property :created, coerce: Time
14
14
  property :modified, coerce: Time
15
- property :revoked, coerce: ->(value) { Stix2.to_bool(value) }
15
+ property :revoked, coerce: Stix2.bool
16
16
  property :labels, coerce: [String]
17
- property :confidence, coerce: ->(value) {
18
- int = Integer(value)
19
- [0..100].include?(int)
20
- int
21
- }
17
+ property :confidence, coerce: Integer
22
18
  property :lang, coerce: String
23
19
  property :external_references, coerce: [ExternalReference]
24
20
  property :object_marking_refs, coerce: [Stix2::MetaObject::DataMarking::ObjectMarking]
25
21
  property :granular_markings, coerce: [MetaObject::DataMarking::GranularMarking]
26
- property :defanged, coerce: ->(value) { Stix2.to_bool(value) }
22
+ property :defanged, coerce: Stix2.bool
27
23
  property :extensions, coerce: Hash
28
24
 
29
25
  def initialize(options = {})
30
- Hashie.symbolize_keys!(options)
31
- type = to_dash(self.class.name.split("::").last)
32
- if options[:type]
33
- if !options[:type].start_with?("x-") && options[:type] != type
34
- raise("Property 'type' must be '#{type}'")
35
- end
36
- else
37
- options[:type] = type
38
- end
39
-
40
- options[:id] ||= "#{type}--#{SecureRandom.uuid}"
41
-
26
+ options_ = options.dup
27
+ Hashie.symbolize_keys!(options_)
28
+ set_strict(options_)
29
+ guess_type(options_)
30
+ autogenerate_id(options_)
42
31
  process_toplevel_property_extension(options[:extensions])
43
- super(options)
44
- process_extensions(options)
32
+ super(options_)
33
+ process_extensions(options_)
34
+ validate_confidence! if @strict
45
35
  Stix2::Storage.add(self)
46
36
  end
47
37
 
@@ -54,9 +44,8 @@ module Stix2
54
44
  end
55
45
  # Retrieve the original method
56
46
  ref_method = m.to_s.gsub(/_instance$/, "")
57
- obj = send(ref_method)
58
- raise("Can't get a Stix2::Identifier from #{ref_method}") if !obj.is_a?(Stix2::Identifier)
59
- Stix2::Storage.find(obj)
47
+ obj_id = public_send(ref_method)
48
+ Stix2::Storage.find(obj_id)
60
49
  end
61
50
 
62
51
  def respond_to_missing?(method_name, include_private = false)
@@ -69,22 +58,35 @@ module Stix2
69
58
 
70
59
  private
71
60
 
72
- def to_dash(string)
73
- string.gsub(/[[:upper:]]/) { "-#{$&.downcase}" }[1..]
61
+ def set_strict(options_)
62
+ @strict = options_.fetch(:strict, false)
63
+ options_.delete(:strict)
64
+ end
65
+
66
+ def guess_type(options)
67
+ type = to_dash(self.class.name.split("::").last)
68
+ if options[:type]
69
+ if !options[:type].start_with?("x-") && options[:type] != type
70
+ raise(Exception::BadType.new(type))
71
+ end
72
+ else
73
+ options[:type] = type
74
+ end
75
+ end
76
+
77
+ def validate_confidence!
78
+ return if !confidence
79
+ valid_range = (0..100)
80
+ valid_range.include?(confidence) || raise(Exception::InvalidRange.new(valid_range, confidence))
74
81
  end
75
82
 
76
- def self.validate_array(list, valid_values)
77
- excess = (Array(list).map(&:to_s) - valid_values.map(&:to_s))
78
- excess.empty? || raise("Invalid values: #{excess}")
79
- list
83
+ def autogenerate_id(options)
84
+ options[:id] ||= "#{options[:type]}--#{SecureRandom.uuid}"
80
85
  end
81
- private_class_method :validate_array
82
86
 
83
- def self.hash_dict(hsh)
84
- validate_array(hsh.keys, HASH_ALGORITHM_OV)
85
- hsh
87
+ def to_dash(string)
88
+ string.gsub(/[[:upper:]]/) { "-#{$&.downcase}" }[1..]
86
89
  end
87
- private_class_method :hash_dict
88
90
 
89
91
  def process_toplevel_property_extension(extensions)
90
92
  extension_definition = extensions&.find { |key, val| key.to_s.start_with?("extension-definition") }
@@ -93,7 +95,7 @@ module Stix2
93
95
  id = extension_definition.first
94
96
  type = extension_definition.last[:extension_type]
95
97
  if type == "toplevel-property-extension"
96
- Stix2::Storage.active? || raise("Stix.storage must be active to use toplevel-property-extension")
98
+ Stix2::Storage.active? || raise(Exception::StorageInactive.new)
97
99
  ext = Stix2::Storage.find(id)
98
100
  ext.extension_properties.each do |prop|
99
101
  self.class.class_eval do
@@ -107,7 +109,7 @@ module Stix2
107
109
  options[:extensions]&.each do |id, value|
108
110
  case id.to_s
109
111
  when /[A-Z]/
110
- raise("Invalid extension name format.")
112
+ raise(Exception::InvalidExtensionNameFormat.new(id))
111
113
  when "archive-ext"
112
114
  extensions[id] = Stix2::Extensions::ArchiveFile.new(value)
113
115
  when /^extension-definition/
@@ -136,7 +138,7 @@ module Stix2
136
138
  extensions[id] = Stix2::Extensions::WindowsPebinary.new(value)
137
139
  else
138
140
  # Ensure we have a hash
139
- value.is_a?(Hash) || raise("Custom extension must be Hash: #{value}")
141
+ value.is_a?(Hash) || raise(Exception::CustomExtensionFormat.new(value))
140
142
  end
141
143
  end
142
144
  end
@@ -1,20 +1,24 @@
1
+ require "rubygems"
2
+
1
3
  module Stix2
2
4
  class CustomObject < Stix2::Common
3
- include Hashie::Extensions::IgnoreUndeclared
5
+ class << self
6
+ extend Gem::Deprecate
7
+ deprecate :new, "Stix2::ExtensionDefinition.new", 2025, 1
8
+ end
4
9
 
5
- property :id, coerce: Identifier
10
+ def initialize(attributes = {})
11
+ attributes.each_key do |attribute|
12
+ self.class.property(attribute) unless self.class.property?(attribute)
13
+ end
6
14
 
7
- def initialize(options)
8
- Hashie.symbolize_keys!(options)
9
- raise("A CustomObject must have at least one property") if options[:type] && options.count == 1
10
- errors = Hash.new { |k, v| k[v] = [] }
11
- options.each do |key, value|
12
- errors["Too short"] << key if key != :id && key.size < 3
13
- errors["Invalid name"] << key if !key.match?(/^[a-z0-9_]*$/)
14
- errors["Too long"] << key if key.size > 250
15
+ super
16
+ h = to_hash
17
+ h.each do |property, value|
18
+ next if property == "id"
19
+ raise(Exception::PropertyInvalidSize.new(property)) if property.size < 3 || property.size > 250
20
+ raise(Exception::PropertyInvalidName.new(property)) if !property.match?(/^[a-z0-9_]*$/)
15
21
  end
16
- raise("Error creating CustomObject: #{errors}") if !errors.empty?
17
- super(options)
18
22
  end
19
23
  end
20
24
  end
@@ -4,9 +4,20 @@ module Stix2
4
4
  property :mime_type, coerce: String
5
5
  property :payload_bin, coerce: String
6
6
  property :url, coerce: String
7
- property :hashes, coerce: ->(hsh) { hash_dict(hsh) }
7
+ property :hashes, coerce: Hash
8
8
  property :encryption_algorithm, values: ENCRYPTION_ALGORITHM_ENUM
9
9
  property :decryption_key, coerce: String
10
+
11
+ def initialize(args = {})
12
+ super
13
+ validate_hashes! if @strict
14
+ end
15
+
16
+ private
17
+
18
+ def validate_hashes!
19
+ Stix2::Validators::Hashes.new(hashes)
20
+ end
10
21
  end
11
22
  end
12
23
  end
@@ -1,7 +1,7 @@
1
1
  module Stix2
2
2
  module CyberobservableObject
3
3
  class EmailMessage < Base
4
- property :is_multipart, required: true, coerce: ->(value) { Stix2.to_bool(value) }
4
+ property :is_multipart, required: true, coerce: Stix2.bool
5
5
  property :date, coerce: Time
6
6
  property :content_type, coerce: String
7
7
  property :from_ref, coerce: Identifier
@@ -1,7 +1,7 @@
1
1
  module Stix2
2
2
  module CyberobservableObject
3
3
  class File < Base
4
- property :hashes, coerce: ->(hsh) { hash_dict(hsh) }
4
+ property :hashes, coerce: Hash
5
5
  property :size, coerce: Integer
6
6
  property :name, coerce: String
7
7
  property :name_enc, coerce: String
@@ -13,6 +13,17 @@ module Stix2
13
13
  property :parent_directory_ref, coerce: Identifier
14
14
  property :contains_refs, coerce: [Identifier]
15
15
  property :content_ref, coerce: Identifier
16
+
17
+ def initialize(args = {})
18
+ super
19
+ validate_hashes! if @strict
20
+ end
21
+
22
+ private
23
+
24
+ def validate_hashes!
25
+ Stix2::Validators::Hashes.new(hashes)
26
+ end
16
27
  end
17
28
  end
18
29
  end
@@ -3,9 +3,20 @@ require "ipaddr"
3
3
  module Stix2
4
4
  module CyberobservableObject
5
5
  class Ipv4Addr < Base
6
- property :value, required: true, coerce: ->(v) { IPAddr.new(v, Socket::AF_INET).to_s }
6
+ property :value, required: true, coerce: String
7
7
  property :resolves_to_refs, coerce: [Identifier]
8
8
  property :resolves_to_refs, coerce: [Identifier]
9
+
10
+ def initialize(args = {})
11
+ super
12
+ validate_ipv4! if @strict
13
+ end
14
+
15
+ private
16
+
17
+ def validate_ipv4!
18
+ IPAddr.new(value, Socket::AF_INET)
19
+ end
9
20
  end
10
21
  end
11
22
  end
@@ -3,9 +3,20 @@ require "ipaddr"
3
3
  module Stix2
4
4
  module CyberobservableObject
5
5
  class Ipv6Addr < Base
6
- property :value, required: true, coerce: ->(v) { IPAddr.new(v, Socket::AF_INET6).to_s }
6
+ property :value, required: true, coerce: String
7
7
  property :resolves_to_refs, coerce: [Identifier]
8
8
  property :resolves_to_refs, coerce: [Identifier]
9
+
10
+ def initialize(args = {})
11
+ super
12
+ validate_ipv6! if @strict
13
+ end
14
+
15
+ private
16
+
17
+ def validate_ipv6!
18
+ IPAddr.new(value, Socket::AF_INET6)
19
+ end
9
20
  end
10
21
  end
11
22
  end
@@ -3,7 +3,7 @@ module Stix2
3
3
  class NetworkTraffic < Base
4
4
  property :start, coerce: Time
5
5
  property :end, coerce: Time
6
- property :is_active, coerce: ->(v) { Stix2.to_bool(v) }
6
+ property :is_active, coerce: Stix2.bool
7
7
  property :src_ref, coerce: Identifier
8
8
  property :dst_ref, coerce: Identifier
9
9
  property :src_port, coerce: Integer
@@ -1,7 +1,7 @@
1
1
  module Stix2
2
2
  module CyberobservableObject
3
3
  class Process < Base
4
- property :is_hidden, coerce: ->(value) { Stix2.to_bool(value) }
4
+ property :is_hidden, coerce: Stix2.bool
5
5
  property :pid, coerce: Integer
6
6
  property :created_time, coerce: Time
7
7
  property :cwd, coerce: String
@@ -6,10 +6,10 @@ module Stix2
6
6
  property :account_login, coerce: String
7
7
  property :account_type, values: ACCOUNT_TYPE_OV
8
8
  property :display_name, coerce: String
9
- property :is_service_account, coerce: ->(value) { Stix2.to_bool(value) }
10
- property :is_privileged, coerce: ->(value) { Stix2.to_bool(value) }
11
- property :can_escalate_privs, coerce: ->(value) { Stix2.to_bool(value) }
12
- property :is_disabled, coerce: ->(value) { Stix2.to_bool(value) }
9
+ property :is_service_account, coerce: Stix2.bool
10
+ property :is_privileged, coerce: Stix2.bool
11
+ property :can_escalate_privs, coerce: Stix2.bool
12
+ property :is_disabled, coerce: Stix2.bool
13
13
  property :account_created, coerce: Time
14
14
  property :account_expires, coerce: Time
15
15
  property :credential_last_changed, coerce: Time
@@ -3,8 +3,8 @@ require "stix2/cyberobservable_objects/x509_v3_extension_type"
3
3
  module Stix2
4
4
  module CyberobservableObject
5
5
  class X509Certificate < Base
6
- property :is_self_signed, coerce: ->(v) { Stix2.to_bool(v) }
7
- property :hashes, coerce: ->(hsh) { hash_dict(hsh) }
6
+ property :is_self_signed, coerce: Stix2.bool
7
+ property :hashes, coerce: Hash
8
8
  property :version, coerce: String
9
9
  property :serial_number, coerce: String
10
10
  property :signature_algorithm, coerce: String
@@ -16,6 +16,17 @@ module Stix2
16
16
  property :subject_public_key_modulus, coerce: String
17
17
  property :subject_public_key_exponent, coerce: String
18
18
  property :x509_v3_extensions, coerce: X509V3ExtensionType
19
+
20
+ def initialize(args = {})
21
+ super
22
+ validate_hashes! if @strict
23
+ end
24
+
25
+ private
26
+
27
+ def validate_hashes!
28
+ Stix2::Validators::Hashes.new(hashes)
29
+ end
19
30
  end
20
31
  end
21
32
  end
@@ -3,13 +3,25 @@ module Stix2
3
3
  class Indicator < Base
4
4
  property :name, coerce: String
5
5
  property :description, coerce: String
6
- property :indicator_types, coerce: ->(v) { validate_array(v, Stix2::INDICATOR_TYPE_OV) }
6
+ property :indicator_types, coerce: [String]
7
+ property :indicator_types
7
8
  property :pattern, coerce: String
8
9
  property :pattern_type, coerce: String, values: PATTERN_TYPE_OV
9
10
  property :pattern_version, coerce: String
10
11
  property :valid_from, coerce: Time
11
12
  property :valid_until, coerce: Time
12
13
  property :kill_chain_phases, coerce: [KillChainPhase]
14
+
15
+ def initialize(args = {})
16
+ super
17
+ validate_indicator_types! if @strict
18
+ end
19
+
20
+ private
21
+
22
+ def validate_indicator_types!
23
+ Stix2::Validators::Array.new(indicator_types, Stix2::INDICATOR_TYPE_OV)
24
+ end
13
25
  end
14
26
  end
15
27
  end
@@ -3,11 +3,22 @@ module Stix2
3
3
  class Infrastructure < Base
4
4
  property :name, required: true, coerce: String
5
5
  property :description, coerce: String
6
- property :infrastructure_types, coerce: ->(v) { validate_array(v, Stix2::INFRASTRUCTURE_TYPE_OV) }
6
+ property :infrastructure_types, coerce: [String]
7
7
  property :aliases, coerce: [String]
8
8
  property :kill_chain_phases, coerce: [KillChainPhase]
9
9
  property :first_seen, coerce: Time
10
10
  property :last_seen, coerce: Time
11
+
12
+ def initialize(args = {})
13
+ super
14
+ validate_infrastructure_types! if @strict
15
+ end
16
+
17
+ private
18
+
19
+ def validate_infrastructure_types!
20
+ Stix2::Validators::Array.new(infrastructure_types, Stix2::INFRASTRUCTURE_TYPE_OV)
21
+ end
11
22
  end
12
23
  end
13
24
  end
@@ -9,7 +9,18 @@ module Stix2
9
9
  property :goals, coerce: [String]
10
10
  property :resource_level, values: ATTACK_RESOURCE_LEVEL_OV
11
11
  property :primary_motivation, values: ATTACK_MOTIVATION_OV
12
- property :secondary_motivations, coerce: ->(v) { validate_array(v, Stix2::ATTACK_MOTIVATION_OV) }
12
+ property :secondary_motivations, coerce: [String]
13
+
14
+ def initialize(args = {})
15
+ super
16
+ validate_secondary_motivations! if @strict
17
+ end
18
+
19
+ private
20
+
21
+ def validate_secondary_motivations!
22
+ Stix2::Validators::Array.new(secondary_motivations, Stix2::ATTACK_MOTIVATION_OV)
23
+ end
13
24
  end
14
25
  end
15
26
  end
@@ -3,17 +3,43 @@ module Stix2
3
3
  class Malware < Base
4
4
  property :name, coerce: String
5
5
  property :description, coerce: String
6
- property :malware_types, coerce: ->(v) { validate_array(v, Stix2::MALWARE_TYPE_OV) }
7
- property :is_family, coerce: ->(v) { Stix2.to_bool(v) }
6
+ property :malware_types, coerce: [String]
7
+ property :is_family, coerce: Stix2.bool
8
8
  property :aliases, coerce: [String]
9
9
  property :kill_chain_phases, coerce: [KillChainPhase]
10
10
  property :first_seen, coerce: Time
11
11
  property :last_seen, coerce: Time
12
12
  property :operating_system_refs, coerce: [Identifier]
13
- property :architecture_execution_envs, coerce: ->(v) { validate_array(v, Stix2::PROCESSOR_ARCHITECTURE_OV) }
14
- property :implementation_languages, coerce: ->(v) { validate_array(v, Stix2::IMPLEMENTATION_LANGUAGE_OV) }
15
- property :capabilities, coerce: ->(v) { validate_array(v, Stix2::IMPLEMENTATION_CAPABILITIES_OV) }
13
+ property :architecture_execution_envs, coerce: [String]
14
+ property :implementation_languages, coerce: [String]
15
+ property :capabilities, coerce: [String]
16
16
  property :sample_refs, coerce: [Identifier]
17
+
18
+ def initialize(args = {})
19
+ super
20
+ validate_malware_types! if @strict
21
+ validate_architecture_execution_envs! if @strict
22
+ validate_implementation_languages! if @strict
23
+ validate_capabilities! if @strict
24
+ end
25
+
26
+ private
27
+
28
+ def validate_malware_types!
29
+ Stix2::Validators::Array.new(malware_types, Stix2::MALWARE_TYPE_OV)
30
+ end
31
+
32
+ def validate_architecture_execution_envs!
33
+ Stix2::Validators::Array.new(architecture_execution_envs, Stix2::PROCESSOR_ARCHITECTURE_OV)
34
+ end
35
+
36
+ def validate_implementation_languages!
37
+ Stix2::Validators::Array.new(implementation_languages, Stix2::IMPLEMENTATION_LANGUAGE_OV)
38
+ end
39
+
40
+ def validate_capabilities!
41
+ Stix2::Validators::Array.new(capabilities, Stix2::IMPLEMENTATION_CAPABILITIES_OV)
42
+ end
17
43
  end
18
44
  end
19
45
  end
@@ -3,9 +3,20 @@ module Stix2
3
3
  class Report < Base
4
4
  property :name, required: true, coerce: String
5
5
  property :description, coerce: String
6
- property :report_types, coerce: ->(v) { validate_array(v, Stix2::REPORT_TYPE_OV) }
6
+ property :report_types, coerce: [String]
7
7
  property :published, coerce: Time
8
8
  property :object_refs, coerce: [Identifier]
9
+
10
+ def initialize(args = {})
11
+ super
12
+ validate_report_types! if @strict
13
+ end
14
+
15
+ private
16
+
17
+ def validate_report_types!
18
+ Stix2::Validators::Array.new(report_types, Stix2::REPORT_TYPE_OV)
19
+ end
9
20
  end
10
21
  end
11
22
  end
@@ -3,17 +3,43 @@ module Stix2
3
3
  class ThreatActor < Base
4
4
  property :name, required: true, coerce: String
5
5
  property :description, coerce: String
6
- property :threat_actor_types, coerce: ->(v) { validate_array(v, THREAT_ACTOR_TYPE_OV) }
6
+ property :threat_actor_types, coerce: [String]
7
7
  property :aliases, coerce: [String]
8
8
  property :first_seen, coerce: Time
9
9
  property :last_seen, coerce: Time
10
- property :roles, coerce: ->(v) { validate_array(v, THREAT_ACTOR_ROLE_OV) }
10
+ property :roles, coerce: [String]
11
11
  property :goals, coerce: [String]
12
12
  property :sophistication, values: THREAT_ACTOR_SOPHISTICATION_OV
13
13
  property :resource_level, values: ATTACK_RESOURCE_LEVEL_OV
14
14
  property :primary_motivation, values: ATTACK_MOTIVATION_OV
15
- property :secondary_motivations, coerce: ->(v) { validate_array(v, ATTACK_MOTIVATION_OV) }
16
- property :personal_motivations, coerce: ->(v) { validate_array(v, ATTACK_MOTIVATION_OV) }
15
+ property :secondary_motivations, coerce: [String]
16
+ property :personal_motivations, coerce: [String]
17
+
18
+ def initialize(args = {})
19
+ super
20
+ validate_threat_actor_types! if @strict
21
+ validate_roles! if @strict
22
+ validate_secondary_motivations! if @strict
23
+ validate_personal_motivations! if @strict
24
+ end
25
+
26
+ private
27
+
28
+ def validate_threat_actor_types!
29
+ Stix2::Validators::Array.new(threat_actor_types, Stix2::THREAT_ACTOR_TYPE_OV)
30
+ end
31
+
32
+ def validate_roles!
33
+ Stix2::Validators::Array.new(roles, Stix2::THREAT_ACTOR_ROLE_OV)
34
+ end
35
+
36
+ def validate_secondary_motivations!
37
+ Stix2::Validators::Array.new(secondary_motivations, Stix2::ATTACK_MOTIVATION_OV)
38
+ end
39
+
40
+ def validate_personal_motivations!
41
+ Stix2::Validators::Array.new(personal_motivations, Stix2::ATTACK_MOTIVATION_OV)
42
+ end
17
43
  end
18
44
  end
19
45
  end
@@ -3,10 +3,21 @@ module Stix2
3
3
  class Tool < Base
4
4
  property :name, required: true, coerce: String
5
5
  property :description, coerce: String
6
- property :tool_types, coerce: ->(v) { validate_array(v, TOOL_TYPES_OV) }
6
+ property :tool_types, coerce: [String]
7
7
  property :aliases, coerce: [String]
8
8
  property :kill_chain_phases, coerce: [KillChainPhase]
9
9
  property :tool_version, coerce: String
10
+
11
+ def initialize(args = {})
12
+ super
13
+ validate_tool_types! if @strict
14
+ end
15
+
16
+ private
17
+
18
+ def validate_tool_types!
19
+ Stix2::Validators::Array.new(tool_types, Stix2::TOOL_TYPES_OV)
20
+ end
10
21
  end
11
22
  end
12
23
  end