ruby-stix2 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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