mihari 7.1.2 → 7.2.0
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 +4 -4
- data/Dockerfile +1 -1
- data/Rakefile +15 -7
- data/build_frontend.sh +1 -1
- data/lefthook.yml +4 -1
- data/lib/mihari/actor.rb +21 -4
- data/lib/mihari/analyzers/base.rb +7 -18
- data/lib/mihari/analyzers/binaryedge.rb +0 -6
- data/lib/mihari/analyzers/censys.rb +0 -9
- data/lib/mihari/analyzers/circl.rb +0 -6
- data/lib/mihari/analyzers/fofa.rb +0 -6
- data/lib/mihari/analyzers/greynoise.rb +0 -6
- data/lib/mihari/analyzers/hunterhow.rb +0 -6
- data/lib/mihari/analyzers/onyphe.rb +0 -6
- data/lib/mihari/analyzers/otx.rb +0 -6
- data/lib/mihari/analyzers/passivetotal.rb +0 -4
- data/lib/mihari/analyzers/pulsedive.rb +0 -6
- data/lib/mihari/analyzers/securitytrails.rb +0 -4
- data/lib/mihari/analyzers/shodan.rb +0 -6
- data/lib/mihari/analyzers/urlscan.rb +0 -6
- data/lib/mihari/analyzers/virustotal.rb +0 -4
- data/lib/mihari/analyzers/virustotal_intelligence.rb +7 -6
- data/lib/mihari/analyzers/zoomeye.rb +0 -6
- data/lib/mihari/commands/web.rb +4 -4
- data/lib/mihari/concerns/falsepositive_normalizable.rb +30 -0
- data/lib/mihari/concerns/falsepositive_validatable.rb +1 -17
- data/lib/mihari/config.rb +1 -1
- data/lib/mihari/database.rb +18 -1
- data/lib/mihari/emitters/database.rb +0 -6
- data/lib/mihari/emitters/misp.rb +0 -6
- data/lib/mihari/emitters/slack.rb +5 -21
- data/lib/mihari/emitters/the_hive.rb +0 -6
- data/lib/mihari/enrichers/whois.rb +5 -7
- data/lib/mihari/entities/artifact.rb +6 -2
- data/lib/mihari/entities/autonomous_system.rb +1 -1
- data/lib/mihari/entities/cpe.rb +1 -1
- data/lib/mihari/entities/port.rb +1 -1
- data/lib/mihari/entities/vulnerability.rb +10 -0
- data/lib/mihari/errors.rb +16 -1
- data/lib/mihari/models/artifact.rb +65 -30
- data/lib/mihari/models/vulnerability.rb +12 -0
- data/lib/mihari/rule.rb +18 -24
- data/lib/mihari/schemas/rule.rb +7 -0
- data/lib/mihari/services/builders.rb +22 -3
- data/lib/mihari/services/enrichers.rb +2 -0
- data/lib/mihari/services/feed.rb +2 -5
- data/lib/mihari/services/proxies.rb +3 -3
- data/lib/mihari/structs/censys.rb +2 -2
- data/lib/mihari/structs/config.rb +3 -20
- data/lib/mihari/structs/greynoise.rb +1 -1
- data/lib/mihari/structs/onyphe.rb +1 -1
- data/lib/mihari/structs/shodan.rb +59 -21
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/artifacts.rb +4 -2
- data/lib/mihari/web/endpoints/rules.rb +1 -1
- data/lib/mihari/web/public/assets/{index-Guw2aMpk.js → index-GWurHG1o.js} +60 -40
- data/lib/mihari/web/public/assets/{index-dVaNxqTC.css → index-ReF8ffd-.css} +1 -1
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +385 -385
- data/lib/mihari.rb +3 -0
- metadata +11 -51
- data/test.json.jbuilder +0 -7
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6b91d99562526b653b793f71e8ef5575f113d26859ca86b91f1980d1c44e898c
         | 
| 4 | 
            +
              data.tar.gz: 07c302ce446b0f0986bfc82dd575ebde203f4b25b73a1aee72a2ce37a08b9b87
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 67d607a09ab2992b6721358b9e96e0c049a355221b2e97358440d70f96ef4933ac86b337bcc12bdc4b2aafccf4e5d6cf8cd68f4b2bbe567523bfba22b7fbd88c
         | 
| 7 | 
            +
              data.tar.gz: 6f73de19824d31e21bae4ee7ce456c1b15fa0a875d1f07025c33ac0356ef257ac2eb819ffd8b685bf8914a472da04f691e5ae02a361397da9a83253d5345b108
         | 
    
        data/Dockerfile
    CHANGED
    
    | @@ -2,7 +2,7 @@ FROM ruby:3.2.2-alpine3.19 | |
| 2 2 |  | 
| 3 3 | 
             
            ARG MIHARI_VERSION=0.0.0
         | 
| 4 4 |  | 
| 5 | 
            -
            RUN apk --no-cache add build-base ruby-dev libpq-dev && \
         | 
| 5 | 
            +
            RUN apk --no-cache add build-base ruby-dev libpq-dev whois && \
         | 
| 6 6 | 
             
              echo 'gem: --no-document' >> /usr/local/etc/gemrc && \
         | 
| 7 7 | 
             
              gem install pg && \
         | 
| 8 8 | 
             
              gem install mihari -v ${MIHARI_VERSION} && \
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            require "time"
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            require "rspec/core/rake_task"
         | 
| 4 6 | 
             
            require "standard/rake"
         | 
| 5 7 |  | 
| @@ -46,18 +48,24 @@ namespace :build do | |
| 46 48 | 
             
              desc "Build Swagger doc"
         | 
| 47 49 | 
             
              task :swagger, [:path] do |_t, args|
         | 
| 48 50 | 
             
                args.with_defaults(path: "./frontend/swagger.yaml")
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                started_at = Time.now
         | 
| 49 53 | 
             
                build_swagger_doc args.path
         | 
| 54 | 
            +
                elapsed = (Time.now - started_at).floor(2)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                puts "Swagger doc is built in #{elapsed}s"
         | 
| 50 57 | 
             
              end
         | 
| 51 58 | 
             
            end
         | 
| 52 59 |  | 
| 53 | 
            -
             | 
| 54 | 
            -
               | 
| 55 | 
            -
            end
         | 
| 60 | 
            +
            task :build do
         | 
| 61 | 
            +
              Rake::Task["build:swagger"].invoke
         | 
| 56 62 |  | 
| 57 | 
            -
             | 
| 58 | 
            -
               | 
| 59 | 
            -
             | 
| 60 | 
            -
               | 
| 63 | 
            +
              # Build ReDocs docs & frontend assets
         | 
| 64 | 
            +
              sh "cd frontend && npm install && npm run docs && npm run build-only"
         | 
| 65 | 
            +
              # Copy built assets into ./lib/web/public/
         | 
| 66 | 
            +
              sh "rm -rf ./lib/mihari/web/public/"
         | 
| 67 | 
            +
              sh "mkdir -p ./lib/mihari/web/public/"
         | 
| 68 | 
            +
              sh "cp -r frontend/dist/* ./lib/mihari/web/public"
         | 
| 61 69 | 
             
            end
         | 
| 62 70 |  | 
| 63 71 | 
             
            # require it later enables doing pre-build step (= build the frontend app)
         | 
    
        data/build_frontend.sh
    CHANGED
    
    
    
        data/lefthook.yml
    CHANGED
    
    | @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            pre-commit:
         | 
| 2 | 
            -
              parallel: true
         | 
| 3 2 | 
             
              commands:
         | 
| 4 3 | 
             
                standard:
         | 
| 5 4 | 
             
                  glob: "*.rb"
         | 
| @@ -15,6 +14,10 @@ pre-commit: | |
| 15 14 | 
             
                  glob: "*.{js,ts,vue}"
         | 
| 16 15 | 
             
                  run: npx prettier --write {staged_files}
         | 
| 17 16 | 
             
                  stage_fixed: true
         | 
| 17 | 
            +
                type-check:
         | 
| 18 | 
            +
                  root: "frontend/"
         | 
| 19 | 
            +
                  glob: "*.{js,ts,vue}"
         | 
| 20 | 
            +
                  run: npm run type-check
         | 
| 18 21 | 
             
                actionlint:
         | 
| 19 22 | 
             
                  glob: ".github/workflows/*.yaml"
         | 
| 20 23 | 
             
                  run: actionlint
         | 
    
        data/lib/mihari/actor.rb
    CHANGED
    
    | @@ -53,10 +53,10 @@ module Mihari | |
| 53 53 | 
             
                def validate_configuration!
         | 
| 54 54 | 
             
                  return if configured?
         | 
| 55 55 |  | 
| 56 | 
            -
                   | 
| 57 | 
            -
                   | 
| 58 | 
            -
             | 
| 59 | 
            -
                  raise ConfigurationError,  | 
| 56 | 
            +
                  message = "#{self.class.type.capitalize}:#{self.class.key} is not configured correctly"
         | 
| 57 | 
            +
                  detail = self.class.configuration_keys.map { |key| "#{key.upcase} is missing" }
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  raise ConfigurationError.new(message, detail)
         | 
| 60 60 | 
             
                end
         | 
| 61 61 |  | 
| 62 62 | 
             
                def call(*args, **kwargs)
         | 
| @@ -92,6 +92,23 @@ module Mihari | |
| 92 92 | 
             
                  def keys
         | 
| 93 93 | 
             
                    ([key] + [key_aliases]).flatten.compact.map(&:downcase)
         | 
| 94 94 | 
             
                  end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  def configuration_keys
         | 
| 97 | 
            +
                    # Automatically generate configuration keys based on key
         | 
| 98 | 
            +
                    # For example,
         | 
| 99 | 
            +
                    # - Shodan analyzer's key is "shodan"
         | 
| 100 | 
            +
                    # - Mihari.config has "shodan_api_key"
         | 
| 101 | 
            +
                    # - Select "shodan_api_key" by using "#{key}_" prefix
         | 
| 102 | 
            +
                    Mihari.config.keys.select { |config_key| config_key.start_with?("#{key}_") }
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  def type
         | 
| 106 | 
            +
                    return "analyzer" if ancestors.include?(Mihari::Analyzers::Base)
         | 
| 107 | 
            +
                    return "emitter" if ancestors.include?(Mihari::Emitters::Base)
         | 
| 108 | 
            +
                    return "enricher" if ancestors.include?(Mihari::Enrichers::Base)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    nil
         | 
| 111 | 
            +
                  end
         | 
| 95 112 | 
             
                end
         | 
| 96 113 | 
             
              end
         | 
| 97 114 | 
             
            end
         | 
| @@ -63,12 +63,10 @@ module Mihari | |
| 63 63 | 
             
                    artifacts.compact.sort.map do |artifact|
         | 
| 64 64 | 
             
                      # No need to set data_type manually
         | 
| 65 65 | 
             
                      # It is set automatically in #initialize
         | 
| 66 | 
            -
                      artifact | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
                       | 
| 70 | 
            -
             | 
| 71 | 
            -
                      artifact
         | 
| 66 | 
            +
                      (artifact.is_a?(Models::Artifact) ? artifact : Models::Artifact.new(data: artifact)).tap do |normalized|
         | 
| 67 | 
            +
                        normalized.source = self.class.key
         | 
| 68 | 
            +
                        normalized.query = query
         | 
| 69 | 
            +
                      end
         | 
| 72 70 | 
             
                    end.select(&:valid?).uniq(&:data)
         | 
| 73 71 | 
             
                  end
         | 
| 74 72 |  | 
| @@ -118,18 +116,9 @@ module Mihari | |
| 118 116 | 
             
                    #
         | 
| 119 117 | 
             
                    # @return [Mihari::Analyzers::Base]
         | 
| 120 118 | 
             
                    #
         | 
| 121 | 
            -
                    def  | 
| 122 | 
            -
                       | 
| 123 | 
            -
             | 
| 124 | 
            -
                      # convert params into arguments for initialization
         | 
| 125 | 
            -
                      query = copied[:query]
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                      # delete analyzer and query
         | 
| 128 | 
            -
                      %i[analyzer query].each { |key| copied.delete key }
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                      copied[:options] = copied[:options] || nil
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                      new(query, **copied)
         | 
| 119 | 
            +
                    def from_params(params)
         | 
| 120 | 
            +
                      query = params.delete(:query)
         | 
| 121 | 
            +
                      new(query, **params)
         | 
| 133 122 | 
             
                    end
         | 
| 134 123 |  | 
| 135 124 | 
             
                    def inherited(child)
         | 
    
        data/lib/mihari/analyzers/otx.rb
    CHANGED
    
    
| @@ -24,12 +24,6 @@ module Mihari | |
| 24 24 | 
             
                    client.intel_search_with_pagination(query, pagination_limit: pagination_limit).map(&:artifacts).flatten
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 |  | 
| 27 | 
            -
                  class << self
         | 
| 28 | 
            -
                    def configuration_keys
         | 
| 29 | 
            -
                      %w[virustotal_api_key]
         | 
| 30 | 
            -
                    end
         | 
| 31 | 
            -
                  end
         | 
| 32 | 
            -
             | 
| 33 27 | 
             
                  class << self
         | 
| 34 28 | 
             
                    #
         | 
| 35 29 | 
             
                    # @return [String]
         | 
| @@ -44,6 +38,13 @@ module Mihari | |
| 44 38 | 
             
                    def key_aliases
         | 
| 45 39 | 
             
                      ["vt_intel"]
         | 
| 46 40 | 
             
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    # @return [Array<String>]
         | 
| 44 | 
            +
                    #
         | 
| 45 | 
            +
                    def configuration_keys
         | 
| 46 | 
            +
                      %w[virustotal_api_key]
         | 
| 47 | 
            +
                    end
         | 
| 47 48 | 
             
                  end
         | 
| 48 49 |  | 
| 49 50 | 
             
                  private
         | 
    
        data/lib/mihari/commands/web.rb
    CHANGED
    
    | @@ -10,10 +10,10 @@ module Mihari | |
| 10 10 | 
             
                    def included(thor)
         | 
| 11 11 | 
             
                      thor.class_eval do
         | 
| 12 12 | 
             
                        desc "web", "Start the web app"
         | 
| 13 | 
            -
                        method_option :port, type: :numeric, default: 9292, desc: " | 
| 14 | 
            -
                        method_option :host, type: :string, default: "localhost", desc: " | 
| 15 | 
            -
                        method_option :threads, type: :string, default: "0: | 
| 16 | 
            -
                        method_option :verbose, type: :boolean, default:  | 
| 13 | 
            +
                        method_option :port, type: :numeric, default: 9292, desc: "Port to listen on"
         | 
| 14 | 
            +
                        method_option :host, type: :string, default: "localhost", desc: "Hostname to listen on"
         | 
| 15 | 
            +
                        method_option :threads, type: :string, default: "0:3", desc: "min:max threads to use"
         | 
| 16 | 
            +
                        method_option :verbose, type: :boolean, default: false, desc: "Don't report each request"
         | 
| 17 17 | 
             
                        method_option :worker_timeout, type: :numeric, default: 60, desc: "Worker timeout value (in seconds)"
         | 
| 18 18 | 
             
                        method_option :open, type: :boolean, default: true, desc: "Whether to open the app in browser or not"
         | 
| 19 19 | 
             
                        method_option :env, type: :string, default: "production", desc: "Environment"
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Mihari
         | 
| 4 | 
            +
              module Concerns
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                # False positive normalizable concern
         | 
| 7 | 
            +
                #
         | 
| 8 | 
            +
                module FalsePositiveNormalizable
         | 
| 9 | 
            +
                  extend ActiveSupport::Concern
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  prepend MemoWise
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  #
         | 
| 14 | 
            +
                  # Normalize a falsepositive value
         | 
| 15 | 
            +
                  #
         | 
| 16 | 
            +
                  # @param [String] value
         | 
| 17 | 
            +
                  #
         | 
| 18 | 
            +
                  # @return [String, Regexp]
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  def normalize_falsepositive(value)
         | 
| 21 | 
            +
                    return value if !value.start_with?("/") || !value.end_with?("/")
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    # if a value is surrounded by slashes, take it as a regexp
         | 
| 24 | 
            +
                    value_without_slashes = value[1..-2]
         | 
| 25 | 
            +
                    Regexp.compile value_without_slashes.to_s
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                  memo_wise :normalize_falsepositive
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -8,23 +8,7 @@ module Mihari | |
| 8 8 | 
             
                module FalsePositiveValidatable
         | 
| 9 9 | 
             
                  extend ActiveSupport::Concern
         | 
| 10 10 |  | 
| 11 | 
            -
                   | 
| 12 | 
            -
             | 
| 13 | 
            -
                  #
         | 
| 14 | 
            -
                  # Normalize a falsepositive value
         | 
| 15 | 
            -
                  #
         | 
| 16 | 
            -
                  # @param [String] value
         | 
| 17 | 
            -
                  #
         | 
| 18 | 
            -
                  # @return [String, Regexp]
         | 
| 19 | 
            -
                  #
         | 
| 20 | 
            -
                  def normalize_falsepositive(value)
         | 
| 21 | 
            -
                    return value if !value.start_with?("/") || !value.end_with?("/")
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                    # if a value is surrounded by slashes, take it as a regexp
         | 
| 24 | 
            -
                    value_without_slashes = value[1..-2]
         | 
| 25 | 
            -
                    Regexp.compile value_without_slashes.to_s
         | 
| 26 | 
            -
                  end
         | 
| 27 | 
            -
                  memo_wise :normalize_falsepositive
         | 
| 11 | 
            +
                  include FalsePositiveNormalizable
         | 
| 28 12 |  | 
| 29 13 | 
             
                  #
         | 
| 30 14 | 
             
                  # Check whether a value is valid format as a disallowed data value
         | 
    
        data/lib/mihari/config.rb
    CHANGED
    
    
    
        data/lib/mihari/database.rb
    CHANGED
    
    | @@ -104,11 +104,28 @@ class V7Schema < ActiveRecord::Migration[7.1] | |
| 104 104 | 
             
              end
         | 
| 105 105 | 
             
            end
         | 
| 106 106 |  | 
| 107 | 
            +
            class V72Schema < ActiveRecord::Migration[7.1]
         | 
| 108 | 
            +
              def change
         | 
| 109 | 
            +
                create_table :vulnerabilities, if_not_exists: true do |t|
         | 
| 110 | 
            +
                  t.string :name, null: false
         | 
| 111 | 
            +
                  t.datetime :created_at
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  t.belongs_to :artifact, foreign_key: true, null: false
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                rename_column :cpes, :cpe, :name if ActiveRecord::Base.connection.column_exists?(:cpes, :cpe)
         | 
| 117 | 
            +
                rename_column :autonomous_systems, :asn, :number if ActiveRecord::Base.connection.column_exists?(
         | 
| 118 | 
            +
                  :autonomous_systems, :asn
         | 
| 119 | 
            +
                )
         | 
| 120 | 
            +
                rename_column :ports, :port, :number if ActiveRecord::Base.connection.column_exists?(:ports, :port)
         | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
            end
         | 
| 123 | 
            +
             | 
| 107 124 | 
             
            #
         | 
| 108 125 | 
             
            # @return [Array<ActiveRecord::Migration>] schemas
         | 
| 109 126 | 
             
            #
         | 
| 110 127 | 
             
            def schemas
         | 
| 111 | 
            -
              [V7Schema]
         | 
| 128 | 
            +
              [V7Schema, V72Schema]
         | 
| 112 129 | 
             
            end
         | 
| 113 130 |  | 
| 114 131 | 
             
            module Mihari
         | 
    
        data/lib/mihari/emitters/misp.rb
    CHANGED
    
    
| @@ -176,21 +176,11 @@ module Mihari | |
| 176 176 | 
             
                  # @return [::Slack::Notifier]
         | 
| 177 177 | 
             
                  #
         | 
| 178 178 | 
             
                  def notifier
         | 
| 179 | 
            -
                    @notifier ||=  | 
| 180 | 
            -
                       | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
                        )
         | 
| 185 | 
            -
                      else
         | 
| 186 | 
            -
                        ::Slack::Notifier.new(
         | 
| 187 | 
            -
                          webhook_url,
         | 
| 188 | 
            -
                          channel: channel,
         | 
| 189 | 
            -
                          username: username,
         | 
| 190 | 
            -
                          http_options: { timeout: timeout }
         | 
| 191 | 
            -
                        )
         | 
| 192 | 
            -
                      end
         | 
| 193 | 
            -
                    end.first
         | 
| 179 | 
            +
                    @notifier ||= lambda do
         | 
| 180 | 
            +
                      return ::Slack::Notifier.new(webhook_url, channel: channel, username: username) if timeout.nil?
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                      ::Slack::Notifier.new(webhook_url, channel: channel, username: username, http_options: { timeout: timeout })
         | 
| 183 | 
            +
                    end.call
         | 
| 194 184 | 
             
                  end
         | 
| 195 185 |  | 
| 196 186 | 
             
                  #
         | 
| @@ -227,12 +217,6 @@ module Mihari | |
| 227 217 |  | 
| 228 218 | 
             
                    notifier.post(text: text, attachments: attachments, mrkdwn: true)
         | 
| 229 219 | 
             
                  end
         | 
| 230 | 
            -
             | 
| 231 | 
            -
                  class << self
         | 
| 232 | 
            -
                    def configuration_keys
         | 
| 233 | 
            -
                      %w[slack_webhook_url slack_channel]
         | 
| 234 | 
            -
                    end
         | 
| 235 | 
            -
                  end
         | 
| 236 220 | 
             
                end
         | 
| 237 221 | 
             
              end
         | 
| 238 222 | 
             
            end
         | 
| @@ -53,13 +53,11 @@ module Mihari | |
| 53 53 | 
             
                  # @return [::Whois::Client]
         | 
| 54 54 | 
             
                  #
         | 
| 55 55 | 
             
                  def whois
         | 
| 56 | 
            -
                    @whois ||=  | 
| 57 | 
            -
                       | 
| 58 | 
            -
             | 
| 59 | 
            -
                       | 
| 60 | 
            -
             | 
| 61 | 
            -
                      end
         | 
| 62 | 
            -
                    end.last
         | 
| 56 | 
            +
                    @whois ||= lambda do
         | 
| 57 | 
            +
                      return ::Whois::Client.new if timeout.nil?
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                      ::Whois::Client.new(timeout: timeout)
         | 
| 60 | 
            +
                    end.call
         | 
| 63 61 | 
             
                  end
         | 
| 64 62 |  | 
| 65 63 | 
             
                  #
         | 
| @@ -8,12 +8,12 @@ module Mihari | |
| 8 8 | 
             
                  expose :data_type, documentation: { type: String, required: true }, as: :dataType
         | 
| 9 9 | 
             
                  expose :source, documentation: { type: String, required: true }
         | 
| 10 10 | 
             
                  expose :query, documentation: { type: String, required: false }
         | 
| 11 | 
            -
                  expose :metadata, documentation: { type: Hash }
         | 
| 12 11 | 
             
                  expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
         | 
| 12 | 
            +
                  expose :tags, using: Entities::Tag, documentation: { type: Entities::Tag, is_array: true, required: true }
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                class Artifact < BaseArtifact
         | 
| 16 | 
            -
                  expose : | 
| 16 | 
            +
                  expose :metadata, documentation: { type: Hash }
         | 
| 17 17 | 
             
                  expose :autonomous_system, using: Entities::AutonomousSystem,
         | 
| 18 18 | 
             
                    documentation: { type: Entities::AutonomousSystem, required: false }, as: :autonomousSystem
         | 
| 19 19 | 
             
                  expose :geolocation, using: Entities::Geolocation, documentation: { type: Entities::Geolocation, required: false }
         | 
| @@ -36,6 +36,10 @@ module Mihari | |
| 36 36 | 
             
                    as: :ports do |status, _options|
         | 
| 37 37 | 
             
                    status.ports.empty? ? nil : status.ports
         | 
| 38 38 | 
             
                  end
         | 
| 39 | 
            +
                  expose :vulnerabilities, using: Vulnerability, documentation: { type: Vulnerability, is_array: true, required: false },
         | 
| 40 | 
            +
                    as: :vulnerabilities do |status, _options|
         | 
| 41 | 
            +
                    status.vulnerabilities.empty? ? nil : status.vulnerabilities
         | 
| 42 | 
            +
                  end
         | 
| 39 43 | 
             
                end
         | 
| 40 44 |  | 
| 41 45 | 
             
                class ArtifactsWithPagination < Pagination
         | 
    
        data/lib/mihari/entities/cpe.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 | 
             
            module Mihari
         | 
| 4 4 | 
             
              module Entities
         | 
| 5 5 | 
             
                class CPE < Grape::Entity
         | 
| 6 | 
            -
                  expose : | 
| 6 | 
            +
                  expose :name, documentation: { type: String, required: true }
         | 
| 7 7 | 
             
                  expose :created_at, documentation: { type: DateTime, required: true }, as: :createdAt
         | 
| 8 8 | 
             
                end
         | 
| 9 9 | 
             
              end
         |