lib/mihari/models/artifact.rb in mihari-6.3.0 vs lib/mihari/models/artifact.rb in mihari-7.0.0

- old
+ new

@@ -20,78 +20,68 @@ belongs_to :alert has_one :autonomous_system, dependent: :destroy has_one :geolocation, dependent: :destroy has_one :whois_record, dependent: :destroy + has_one :rule, through: :alert has_many :cpes, dependent: :destroy has_many :dns_records, dependent: :destroy has_many :ports, dependent: :destroy has_many :reverse_dns_names, dependent: :destroy + has_many :tags, through: :alert include ActiveModel::Validations + include SearchCop + include Concerns::Searchable + search_scope :search do + attributes :id, :data, :data_type, :source, :query, :created_at, "alert.id", "rule.id", "rule.title", + "rule.description" + attributes tag: "tags.name" + attributes asn: "autonomous_system.asn" + attributes country_code: "geolocation.country_code" + attributes "dns_record.value": "dns_records.value" + attributes "dns_record.resource": "dns_records.resource" + attributes reverse_dns_name: "reverse_dns_names.name" + attributes cpe: "cpes.name" + attributes port: "ports.port" + end + validates_with ArtifactValidator - # @return [Array<Mihari::Tag>] Tags - attr_accessor :tags + after_initialize :set_data_type, :set_rule_id, if: :new_record? - # @return [String, nil] Rule ID + # @return [String, nil] attr_accessor :rule_id - def initialize(*args, **kwargs) - attrs = args.first || kwargs - data_ = attrs[:data] - - raise TypeError if data_.is_a?(Array) || data_.is_a?(Hash) - - super(*args, **kwargs) - - self.data_type = DataType.type(data) - - @tags = [] - @rule_id = "" - end - # - # Check uniqueness of artifact + # Check uniqueness # # @param [Time, nil] base_time Base time to check decaying - # @param [Integer, nil] artifact_lifetime Artifact lifetime (TTL) in seconds + # @param [Integer, nil] artifact_ttl Artifact TTL in seconds # # @return [Boolean] true if it is unique. Otherwise false. # - def unique?(base_time: nil, artifact_lifetime: nil) + def unique?(base_time: nil, artifact_ttl: nil) artifact = self.class.joins(:alert).where( data: data, alert: { rule_id: rule_id } ).order(created_at: :desc).first return true if artifact.nil? # check whether the artifact is decayed or not - return false if artifact_lifetime.nil? + 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_lifetime || -1).seconds + decayed_at = base_time - (artifact_ttl || -1).seconds artifact.created_at < decayed_at end # - # Count artifacts - # - # @param [Mihari::Structs::Filters::Artifact::SearchFilter] filter - # - # @return [Integer] - # - def count(filter) - relation = build_relation(filter) - relation.distinct("artifact.id").count - end - - # # Enrich whois record # # @param [Mihari::Enrichers::Whois] enricher # def enrich_whois(enricher = Enrichers::Whois.new) @@ -125,22 +115,22 @@ # # Enrich geolocation # # @param [Mihari::Enrichers::IPInfo] enricher # - def enrich_geolocation(enricher = Enrichers::IPInfo.new) + def enrich_geolocation(enricher = Enrichers::MMDB.new) return unless can_enrich_geolocation? self.geolocation = Geolocation.build_by_ip(data, enricher: enricher) end # # Enrich AS # # @param [Mihari::Enrichers::IPInfo] enricher # - def enrich_autonomous_system(enricher = Enrichers::IPInfo.new) + def enrich_autonomous_system(enricher = Enrichers::MMDB.new) return unless can_enrich_autonomous_system? self.autonomous_system = AutonomousSystem.build_by_ip(data, enricher: enricher) end @@ -168,24 +158,24 @@ # # Enrich all the enrichable relationships of the artifact # def enrich_all - enrich_autonomous_system ipinfo + enrich_autonomous_system mmdb enrich_dns - enrich_geolocation ipinfo + enrich_geolocation mmdb enrich_reverse_dns shodan enrich_whois enrich_ports shodan enrich_cpes shodan end ENRICH_METHODS_BY_ENRICHER = { Enrichers::Whois => %i[ enrich_whois ], - Enrichers::IPInfo => %i[ + Enrichers::MMDB => %i[ enrich_autonomous_system enrich_geolocation ], Enrichers::Shodan => %i[ enrich_ports @@ -206,62 +196,30 @@ methods = ENRICH_METHODS_BY_ENRICHER[enricher.class] || [] methods.each { |method| send(method, enricher) if respond_to?(method) } end class << self - # - # Search artifacts - # - # @param [Mihari::Structs::Filters::Artifact::SearchFilterWithPagination] filter - # - # @return [Array<Artifact>] - # - def search(filter) - limit = filter.limit.to_i - raise ArgumentError, "limit should be bigger than zero" unless limit.positive? + # @!method search_by_filter(filter) + # @param [Mihari::Structs::Filters::Search] filter + # @return [Array<Mihari::Models::Alert>] - page = filter.page.to_i - raise ArgumentError, "page should be bigger than zero" unless page.positive? + # @!method count_by_filter(filter) + # @param [Mihari::Structs::Filters::Search] filter + # @return [Integer] + end - offset = (page - 1) * limit + private - relation = build_relation(filter.without_pagination) - relation.limit(limit).offset(offset).order(id: :desc) - end + def set_data_type + self.data_type = DataType.type(data) + end - # - # Count artifacts - # - # @param [Mihari::Structs::Filters::Artifact::SearchFilter] filter - # - # @return [Integer] - # - def count(filter) - relation = build_relation(filter) - relation.distinct("artifacts.id").count - end - - # - # @param [Mihari::Structs::Filters::Artifact::SearchFilter] filter - # - # @return [Mihari::Models::Artifact] - # - def build_relation(filter) - relation = eager_load(alert: :tags) - - relation = relation.where(alert: { rule_id: filter.rule_id }) if filter.rule_id - relation = relation.where(alert: { tags: { name: filter.tag } }) if filter.tag - relation = relation.where("artifacts.created_at >= ?", filter.from_at) if filter.from_at - relation = relation.where("artifacts.created_at <= ?", filter.to_at) if filter.to_at - - relation - end + def set_rule_id + @set_rule_id ||= nil end - private - - def ipinfo - @ipinfo ||= Enrichers::IPInfo.new + def mmdb + @mmdb ||= Enrichers::MMDB.new end def shodan @shodan ||= Enrichers::Shodan.new end