Class: Mihari::Models::Artifact

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
ActiveModel::Validations, Concerns::Searchable, SearchCop
Defined in:
lib/mihari/models/artifact.rb

Overview

Artifact model

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#alertMihari::Models::Alert (readonly)



# File 'lib/mihari/models/artifact.rb', line 43


#autonomous_systemMihari::Models::AutonomousSystem?



# File 'lib/mihari/models/artifact.rb', line 49


#cpesArray<Mihari::Models::CPE>

Returns:



# File 'lib/mihari/models/artifact.rb', line 58


#created_atDateTime

Returns:

  • (DateTime)


# File 'lib/mihari/models/artifact.rb', line 40


#dataString

Returns:

  • (String)


# File 'lib/mihari/models/artifact.rb', line 25


#data_typeString

Returns:

  • (String)


# File 'lib/mihari/models/artifact.rb', line 28


#dns_recordsArray<Mihari::Models::DnsRecord>

Returns:



# File 'lib/mihari/models/artifact.rb', line 61


#geolocationMihari::Models::Geolocation?

Returns:



# File 'lib/mihari/models/artifact.rb', line 52


#idInteger? (readonly)

Returns:

  • (Integer, nil)


# File 'lib/mihari/models/artifact.rb', line 22


#metadataHash?

Returns:

  • (Hash, nil)


# File 'lib/mihari/models/artifact.rb', line 37


#portsArray<Mihari::Models::Port>

Returns:



# File 'lib/mihari/models/artifact.rb', line 64


#queryString?

Returns:

  • (String, nil)


# File 'lib/mihari/models/artifact.rb', line 34


#reverse_dns_namesArray<Mihari::Models::ReverseDnsName>

Returns:



# File 'lib/mihari/models/artifact.rb', line 67


#ruleMihari::Models::Rule (readonly)



# File 'lib/mihari/models/artifact.rb', line 46


#rule_idString?

Returns:

  • (String, nil)


144
145
146
# File 'lib/mihari/models/artifact.rb', line 144

def rule_id
  @rule_id
end

#sourceString?

Returns:

  • (String, nil)


# File 'lib/mihari/models/artifact.rb', line 31


#tagsArray<Mihari::Models::Tag>

Returns:



106
# File 'lib/mihari/models/artifact.rb', line 106

belongs_to :alert

#vulnerabilitiesArray<Mihari::Models::Vulnerability>

Returns:



# File 'lib/mihari/models/artifact.rb', line 70


#whois_recordMihari::Models::WhoisRecord?

Returns:



# File 'lib/mihari/models/artifact.rb', line 55


Instance Method Details

#count_by_filter(filter) ⇒ Integer

Parameters:

Returns:

  • (Integer)


# File 'lib/mihari/models/artifact.rb', line 239


#domainString?

Returns:

  • (String, nil)


212
213
214
215
216
217
218
219
220
# File 'lib/mihari/models/artifact.rb', line 212

def domain
  case data_type
  when "domain"
    data
  when "url"
    host = Addressable::URI.parse(data).host
    (DataType.type(host) == "ip") ? nil : host
  end
end

#enrichObject



180
181
182
# File 'lib/mihari/models/artifact.rb', line 180

def enrich
  enrich_by_enrichers callable_enrichers
end

#enrich_by_enrichers(enrichers) ⇒ Mihari::Models::Artifact

Parameters:

Returns:



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/mihari/models/artifact.rb', line 190

def enrich_by_enrichers(enrichers)
  # NOTE: doing parallel with ActiveRecord objects is troublesome (e.g. connection issue, etc.)
  #       so converting the object to an OpenStruct object
  s = struct
  results = Parallel.map(enrichers) { |enricher| enricher.result s }
  enriched = results.compact.map { |result| result.value_or(nil) }.compact

  self.dns_records = enriched.map(&:dns_records).flatten.compact
  self.cpes = enriched.map(&:cpes).flatten.compact
  self.ports = enriched.map(&:ports).flatten.compact
  self.vulnerabilities = enriched.map(&:vulnerabilities).flatten.compact

  self.autonomous_system = enriched.map(&:autonomous_system).compact.first
  self.geolocation = enriched.map(&:geolocation).compact.first
  self.whois_record = enriched.map(&:whois_record).compact.first

  self
end

#enrichable?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'lib/mihari/models/artifact.rb', line 176

def enrichable?
  !callable_enrichers.empty?
end

#search_by_filter(filter) ⇒ Array<Mihari::Models::Alert>

Parameters:

Returns:



# File 'lib/mihari/models/artifact.rb', line 235


#structObject



222
223
224
225
226
227
228
229
230
231
232
# File 'lib/mihari/models/artifact.rb', line 222

def struct
  OpenStruct.new(attributes).tap do |s|
    s.domain = domain
    s.cpes ||= []
    s.dns_records ||= []
    s.ports ||= []
    s.reverse_dns_names ||= []
    s.vulnerabilities ||= []
    s.tags ||= []
  end
end

#unique?(base_time: nil, artifact_ttl: nil) ⇒ Boolean

Check uniqueness

Parameters:

  • base_time (Time, nil) (defaults to: nil)

    Base time to check decaying

  • artifact_ttl (Integer, nil) (defaults to: nil)

    Artifact TTL in seconds

Returns:

  • (Boolean)

    true if it is unique. Otherwise false.



162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/mihari/models/artifact.rb', line 162

def unique?(base_time: nil, artifact_ttl: nil)
  artifact = self.class.joins(:alert).where(data:, alert: {rule_id:}).order(created_at: :desc).first
  return true if artifact.nil?

  # check whether the artifact is decayed or not
  return false if artifact_ttl.nil?

  # use the current UTC time if base_time is not given (for testing)
  base_time ||= Time.now.utc

  decayed_at = base_time - (artifact_ttl || -1).seconds
  artifact.created_at < decayed_at
end