mihari 7.1.1 → 7.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +9 -8
- data/build_frontend.sh +1 -1
- data/lib/mihari/actor.rb +16 -8
- data/lib/mihari/analyzers/base.rb +12 -3
- data/lib/mihari/analyzers/passivetotal.rb +1 -1
- data/lib/mihari/analyzers/securitytrails.rb +1 -1
- data/lib/mihari/analyzers/virustotal.rb +1 -1
- data/lib/mihari/analyzers/virustotal_intelligence.rb +2 -2
- data/lib/mihari/commands/web.rb +3 -3
- data/lib/mihari/constants.rb +1 -1
- data/lib/mihari/emitters/base.rb +11 -1
- data/lib/mihari/emitters/database.rb +4 -0
- data/lib/mihari/emitters/misp.rb +7 -0
- data/lib/mihari/emitters/slack.rb +7 -0
- data/lib/mihari/emitters/the_hive.rb +7 -0
- data/lib/mihari/emitters/webhook.rb +7 -0
- data/lib/mihari/enrichers/base.rb +3 -1
- data/lib/mihari/enrichers/google_public_dns.rb +1 -1
- data/lib/mihari/errors.rb +14 -1
- data/lib/mihari/schemas/analyzer.rb +19 -19
- data/lib/mihari/schemas/emitter.rb +5 -5
- data/lib/mihari/schemas/enricher.rb +4 -4
- data/lib/mihari/structs/config.rb +4 -21
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/public/assets/{index-U5u7qHZZ.js → index-TOeU8PE2.js} +75 -55
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari/web/public/redoc-static.html +384 -384
- data/lib/mihari.rb +3 -3
- data/mihari.gemspec +4 -4
- metadata +11 -12
- 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: d7463506c12a2476cfea5dda939e88e01150fb6539c232e102c15fca4c57ab99
|
4
|
+
data.tar.gz: fdb700f461140badc1d90b3199999a97e483e57ae9c9bfed2d0157a94f35529d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18d9dd1f63056cd2731caa823904fd9df80ca21e63a540eab89d06e7951fa10cde498344049f3ba7de8740da2e8cfb9da9fe660f77c3a1abca5e308e36a6973c
|
7
|
+
data.tar.gz: 5a8ce97455cb0e68538af1ca2c8af5b89ea96f817d4f11cf6c00851035a20288f9bc2d2de16b58b52f3e72e988c77a2e4d8744a3fbebfd27c2cb6895d4c4dccb
|
data/Rakefile
CHANGED
@@ -50,14 +50,15 @@ namespace :build do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
task :build do
|
54
|
+
# Build Swagger dos
|
55
|
+
Rake::Task["build:swagger"].invoke
|
56
|
+
# Build ReDocs docs & frontend assets
|
57
|
+
sh "cd frontend && npm install && npm run docs && npm run build-only"
|
58
|
+
# Copy built assets into ./lib/web/public/
|
59
|
+
sh "rm -rf ./lib/mihari/web/public/"
|
60
|
+
sh "mkdir -p ./lib/mihari/web/public/"
|
61
|
+
sh "cp -r frontend/dist/* ./lib/mihari/web/public"
|
61
62
|
end
|
62
63
|
|
63
64
|
# require it later enables doing pre-build step (= build the frontend app)
|
data/build_frontend.sh
CHANGED
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)
|
@@ -75,22 +75,30 @@ module Mihari
|
|
75
75
|
#
|
76
76
|
# @return [String]
|
77
77
|
#
|
78
|
-
def
|
78
|
+
def key
|
79
79
|
to_s.split("::").last.downcase
|
80
80
|
end
|
81
81
|
|
82
82
|
#
|
83
83
|
# @return [Array<String>, nil]
|
84
84
|
#
|
85
|
-
def
|
85
|
+
def key_aliases
|
86
86
|
nil
|
87
87
|
end
|
88
88
|
|
89
89
|
#
|
90
90
|
# @return [Array<String>]
|
91
91
|
#
|
92
|
-
def
|
93
|
-
([
|
92
|
+
def keys
|
93
|
+
([key] + [key_aliases]).flatten.compact.map(&:downcase)
|
94
|
+
end
|
95
|
+
|
96
|
+
def type
|
97
|
+
return "analyzer" if ancestors.include?(Mihari::Analyzers::Base)
|
98
|
+
return "emitter" if ancestors.include?(Mihari::Emitters::Base)
|
99
|
+
return "enricher" if ancestors.include?(Mihari::Enrichers::Base)
|
100
|
+
|
101
|
+
nil
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|
@@ -65,7 +65,7 @@ module Mihari
|
|
65
65
|
# It is set automatically in #initialize
|
66
66
|
artifact = artifact.is_a?(Models::Artifact) ? artifact : Models::Artifact.new(data: artifact)
|
67
67
|
|
68
|
-
artifact.source = self.class.
|
68
|
+
artifact.source = self.class.key
|
69
69
|
artifact.query = query
|
70
70
|
|
71
71
|
artifact
|
@@ -93,14 +93,23 @@ module Mihari
|
|
93
93
|
return result if result.success?
|
94
94
|
|
95
95
|
# Wrap failure with AnalyzerError to explicitly name a failed analyzer
|
96
|
-
error = AnalyzerError.new(result.failure.message, self.class.
|
96
|
+
error = AnalyzerError.new(result.failure.message, self.class.key, cause: result.failure)
|
97
97
|
return Failure(error) unless ignore_error?
|
98
98
|
|
99
99
|
# Return Success if ignore_error? is true with logging
|
100
|
-
Mihari.logger.warn("Analyzer:#{self.class.
|
100
|
+
Mihari.logger.warn("Analyzer:#{self.class.key} with #{truncated_query} failed - #{result.failure}")
|
101
101
|
Success([])
|
102
102
|
end
|
103
103
|
|
104
|
+
#
|
105
|
+
# Truncate query for logging
|
106
|
+
#
|
107
|
+
# @return [String]
|
108
|
+
#
|
109
|
+
def truncated_query
|
110
|
+
query.truncate(32)
|
111
|
+
end
|
112
|
+
|
104
113
|
class << self
|
105
114
|
#
|
106
115
|
# Initialize an analyzer by query params
|
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: "
|
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
15
|
method_option :threads, type: :string, default: "0:5", desc: "min:max threads to use"
|
16
|
-
method_option :verbose, type: :boolean, default:
|
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"
|
data/lib/mihari/constants.rb
CHANGED
@@ -5,7 +5,7 @@ module Mihari
|
|
5
5
|
DEFAULT_DATA_TYPES = Types::DataTypes.values.freeze
|
6
6
|
|
7
7
|
# @return [Array<Hash>]
|
8
|
-
DEFAULT_EMITTERS = Emitters::Database.
|
8
|
+
DEFAULT_EMITTERS = Emitters::Database.keys.map { |name| { emitter: name.downcase } }.freeze
|
9
9
|
|
10
10
|
# @return [Array<Hash>]
|
11
11
|
DEFAULT_ENRICHERS = Mihari.enricher_to_class.keys.map { |name| { enricher: name.downcase } }.freeze
|
data/lib/mihari/emitters/base.rb
CHANGED
@@ -19,6 +19,14 @@ module Mihari
|
|
19
19
|
@rule = rule
|
20
20
|
end
|
21
21
|
|
22
|
+
# A target to emit the data
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
#
|
26
|
+
def target
|
27
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
28
|
+
end
|
29
|
+
|
22
30
|
#
|
23
31
|
# @param [Array<Mihari::Models::Artifact>] artifacts
|
24
32
|
#
|
@@ -38,7 +46,9 @@ module Mihari
|
|
38
46
|
) { call(artifacts) }
|
39
47
|
end.to_result
|
40
48
|
|
41
|
-
|
49
|
+
if result.failure?
|
50
|
+
Mihari.logger.warn("Emitter:#{self.class.key} for #{target.truncate(32)} failed - #{result.failure}")
|
51
|
+
end
|
42
52
|
|
43
53
|
result
|
44
54
|
end
|
data/lib/mihari/emitters/misp.rb
CHANGED
@@ -33,7 +33,9 @@ module Mihari
|
|
33
33
|
) { call value }
|
34
34
|
end.to_result
|
35
35
|
|
36
|
-
|
36
|
+
if result.failure?
|
37
|
+
Mihari.logger.warn("Enricher:#{self.class.key} for #{value.truncate(32)} failed: #{result.failure}")
|
38
|
+
end
|
37
39
|
|
38
40
|
result
|
39
41
|
end
|
data/lib/mihari/errors.rb
CHANGED
@@ -7,7 +7,20 @@ module Mihari
|
|
7
7
|
|
8
8
|
class ValueError < Error; end
|
9
9
|
|
10
|
-
class ConfigurationError < Error
|
10
|
+
class ConfigurationError < Error
|
11
|
+
# @return [Array<String>, nil]
|
12
|
+
attr_reader :detail
|
13
|
+
|
14
|
+
#
|
15
|
+
# @param [String] msg
|
16
|
+
# @param [Array<String>, nil] detail
|
17
|
+
#
|
18
|
+
def initialize(msg, detail)
|
19
|
+
super(msg)
|
20
|
+
|
21
|
+
@detail = detail
|
22
|
+
end
|
23
|
+
end
|
11
24
|
|
12
25
|
class ResponseError < Error; end
|
13
26
|
|
@@ -10,12 +10,12 @@ module Mihari
|
|
10
10
|
|
11
11
|
# Analyzer with API key and pagination
|
12
12
|
[
|
13
|
-
Mihari::Analyzers::BinaryEdge.
|
14
|
-
Mihari::Analyzers::GreyNoise.
|
15
|
-
Mihari::Analyzers::Onyphe.
|
16
|
-
Mihari::Analyzers::Shodan.
|
17
|
-
Mihari::Analyzers::Urlscan.
|
18
|
-
Mihari::Analyzers::VirusTotalIntelligence.
|
13
|
+
Mihari::Analyzers::BinaryEdge.keys,
|
14
|
+
Mihari::Analyzers::GreyNoise.keys,
|
15
|
+
Mihari::Analyzers::Onyphe.keys,
|
16
|
+
Mihari::Analyzers::Shodan.keys,
|
17
|
+
Mihari::Analyzers::Urlscan.keys,
|
18
|
+
Mihari::Analyzers::VirusTotalIntelligence.keys
|
19
19
|
].each do |keys|
|
20
20
|
key = keys.first
|
21
21
|
const_set(key.upcase, Dry::Schema.Params do
|
@@ -28,10 +28,10 @@ module Mihari
|
|
28
28
|
|
29
29
|
# Analyzer with API key
|
30
30
|
[
|
31
|
-
Mihari::Analyzers::OTX.
|
32
|
-
Mihari::Analyzers::Pulsedive.
|
33
|
-
Mihari::Analyzers::VirusTotal.
|
34
|
-
Mihari::Analyzers::SecurityTrails.
|
31
|
+
Mihari::Analyzers::OTX.keys,
|
32
|
+
Mihari::Analyzers::Pulsedive.keys,
|
33
|
+
Mihari::Analyzers::VirusTotal.keys,
|
34
|
+
Mihari::Analyzers::SecurityTrails.keys
|
35
35
|
].each do |keys|
|
36
36
|
key = keys.first
|
37
37
|
const_set(key.upcase, Dry::Schema.Params do
|
@@ -43,13 +43,13 @@ module Mihari
|
|
43
43
|
end
|
44
44
|
|
45
45
|
DNSTwister = Dry::Schema.Params do
|
46
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::DNSTwister.
|
46
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::DNSTwister.keys))
|
47
47
|
required(:query).value(:string)
|
48
48
|
optional(:options).hash(AnalyzerOptions)
|
49
49
|
end
|
50
50
|
|
51
51
|
Censys = Dry::Schema.Params do
|
52
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Censys.
|
52
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Censys.keys))
|
53
53
|
required(:query).value(:string)
|
54
54
|
optional(:id).value(:string)
|
55
55
|
optional(:secret).value(:string)
|
@@ -57,7 +57,7 @@ module Mihari
|
|
57
57
|
end
|
58
58
|
|
59
59
|
CIRCL = Dry::Schema.Params do
|
60
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::CIRCL.
|
60
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::CIRCL.keys))
|
61
61
|
required(:query).value(:string)
|
62
62
|
optional(:username).value(:string)
|
63
63
|
optional(:password).value(:string)
|
@@ -65,7 +65,7 @@ module Mihari
|
|
65
65
|
end
|
66
66
|
|
67
67
|
Fofa = Dry::Schema.Params do
|
68
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Fofa.
|
68
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Fofa.keys))
|
69
69
|
required(:query).value(:string)
|
70
70
|
optional(:api_key).value(:string)
|
71
71
|
optional(:email).value(:string)
|
@@ -73,7 +73,7 @@ module Mihari
|
|
73
73
|
end
|
74
74
|
|
75
75
|
PassiveTotal = Dry::Schema.Params do
|
76
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::PassiveTotal.
|
76
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::PassiveTotal.keys))
|
77
77
|
required(:query).value(:string)
|
78
78
|
optional(:username).value(:string)
|
79
79
|
optional(:api_key).value(:string)
|
@@ -81,14 +81,14 @@ module Mihari
|
|
81
81
|
end
|
82
82
|
|
83
83
|
ZoomEye = Dry::Schema.Params do
|
84
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::ZoomEye.
|
84
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::ZoomEye.keys))
|
85
85
|
required(:query).value(:string)
|
86
86
|
required(:type).value(Types::String.enum("host", "web"))
|
87
87
|
optional(:options).hash(AnalyzerPaginationOptions)
|
88
88
|
end
|
89
89
|
|
90
90
|
Crtsh = Dry::Schema.Params do
|
91
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Crtsh.
|
91
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Crtsh.keys))
|
92
92
|
required(:query).value(:string)
|
93
93
|
optional(:exclude_expired).value(:bool).default(true)
|
94
94
|
optional(:match).value(Types::String.enum("=", "ILIKE", "LIKE", "single", "any", "FTS")).default(nil)
|
@@ -96,7 +96,7 @@ module Mihari
|
|
96
96
|
end
|
97
97
|
|
98
98
|
HunterHow = Dry::Schema.Params do
|
99
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::HunterHow.
|
99
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::HunterHow.keys))
|
100
100
|
required(:query).value(:string)
|
101
101
|
required(:start_time).value(:date)
|
102
102
|
required(:end_time).value(:date)
|
@@ -105,7 +105,7 @@ module Mihari
|
|
105
105
|
end
|
106
106
|
|
107
107
|
Feed = Dry::Schema.Params do
|
108
|
-
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Feed.
|
108
|
+
required(:analyzer).value(Types::String.enum(*Mihari::Analyzers::Feed.keys))
|
109
109
|
required(:query).value(:string)
|
110
110
|
required(:selector).value(:string)
|
111
111
|
optional(:method).value(Types::HTTPRequestMethods).default("GET")
|
@@ -9,33 +9,33 @@ module Mihari
|
|
9
9
|
extend Concerns::Orrable
|
10
10
|
|
11
11
|
Database = Dry::Schema.Params do
|
12
|
-
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Database.
|
12
|
+
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Database.keys))
|
13
13
|
optional(:options).hash(Options)
|
14
14
|
end
|
15
15
|
|
16
16
|
MISP = Dry::Schema.Params do
|
17
|
-
required(:emitter).value(Types::String.enum(*Mihari::Emitters::MISP.
|
17
|
+
required(:emitter).value(Types::String.enum(*Mihari::Emitters::MISP.keys))
|
18
18
|
optional(:url).value(:string)
|
19
19
|
optional(:api_key).value(:string)
|
20
20
|
optional(:options).hash(Options)
|
21
21
|
end
|
22
22
|
|
23
23
|
TheHive = Dry::Schema.Params do
|
24
|
-
required(:emitter).value(Types::String.enum(*Mihari::Emitters::TheHive.
|
24
|
+
required(:emitter).value(Types::String.enum(*Mihari::Emitters::TheHive.keys))
|
25
25
|
optional(:url).value(:string)
|
26
26
|
optional(:api_key).value(:string)
|
27
27
|
optional(:options).hash(Options)
|
28
28
|
end
|
29
29
|
|
30
30
|
Slack = Dry::Schema.Params do
|
31
|
-
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Slack.
|
31
|
+
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Slack.keys))
|
32
32
|
optional(:webhook_url).value(:string)
|
33
33
|
optional(:channel).value(:string)
|
34
34
|
optional(:options).hash(Options)
|
35
35
|
end
|
36
36
|
|
37
37
|
Webhook = Dry::Schema.Params do
|
38
|
-
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Webhook.
|
38
|
+
required(:emitter).value(Types::String.enum(*Mihari::Emitters::Webhook.keys))
|
39
39
|
required(:url).value(:string)
|
40
40
|
optional(:method).value(Types::HTTPRequestMethods).default("POST")
|
41
41
|
optional(:headers).value(:hash).default({})
|
@@ -9,22 +9,22 @@ module Mihari
|
|
9
9
|
extend Concerns::Orrable
|
10
10
|
|
11
11
|
MMDB = Dry::Schema.Params do
|
12
|
-
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::MMDB.
|
12
|
+
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::MMDB.keys))
|
13
13
|
optional(:options).hash(Options)
|
14
14
|
end
|
15
15
|
|
16
16
|
Whois = Dry::Schema.Params do
|
17
|
-
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::Whois.
|
17
|
+
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::Whois.keys))
|
18
18
|
optional(:options).hash(Options)
|
19
19
|
end
|
20
20
|
|
21
21
|
Shodan = Dry::Schema.Params do
|
22
|
-
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::Shodan.
|
22
|
+
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::Shodan.keys))
|
23
23
|
optional(:options).hash(Options)
|
24
24
|
end
|
25
25
|
|
26
26
|
GooglePublicDNS = Dry::Schema.Params do
|
27
|
-
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::GooglePublicDNS.
|
27
|
+
required(:enricher).value(Types::String.enum(*Mihari::Enrichers::GooglePublicDNS.keys))
|
28
28
|
optional(:options).hash(Options)
|
29
29
|
end
|
30
30
|
end
|
@@ -20,21 +20,6 @@ module Mihari
|
|
20
20
|
attribute :items, Types.Array(Types::Hash).optional
|
21
21
|
|
22
22
|
class << self
|
23
|
-
#
|
24
|
-
# Get a type of a class
|
25
|
-
#
|
26
|
-
# @param [Class<Mihari::Analyzers::Base>, Class<Mihari::Emitters::Base>, Class<Mihari::Enrichers::Base>] klass
|
27
|
-
#
|
28
|
-
# @return [String, nil]
|
29
|
-
#
|
30
|
-
def get_type(klass)
|
31
|
-
return "analyzer" if klass.ancestors.include?(Mihari::Analyzers::Base)
|
32
|
-
return "emitter" if klass.ancestors.include?(Mihari::Emitters::Base)
|
33
|
-
return "enricher" if klass.ancestors.include?(Mihari::Enrichers::Base)
|
34
|
-
|
35
|
-
nil
|
36
|
-
end
|
37
|
-
|
38
23
|
#
|
39
24
|
# Get a dummy instance
|
40
25
|
#
|
@@ -43,8 +28,7 @@ module Mihari
|
|
43
28
|
# @return [Mihari::Analyzers::Base, Mihari::Emitter::Base, Mihari::Enricher::Base] dummy
|
44
29
|
#
|
45
30
|
def get_dummy(klass)
|
46
|
-
|
47
|
-
case type
|
31
|
+
case klass.type
|
48
32
|
when "analyzer"
|
49
33
|
klass.new("dummy")
|
50
34
|
when "emitter"
|
@@ -62,16 +46,15 @@ module Mihari
|
|
62
46
|
def from_class(klass)
|
63
47
|
return nil if klass == Mihari::Rule
|
64
48
|
|
65
|
-
|
66
|
-
return nil if type.nil?
|
49
|
+
return nil if klass.type.nil?
|
67
50
|
|
68
51
|
begin
|
69
52
|
instance = get_dummy(klass)
|
70
53
|
new(
|
71
|
-
name: klass.
|
54
|
+
name: klass.key,
|
72
55
|
items: klass.configuration_items,
|
73
56
|
configured: instance.configured?,
|
74
|
-
type: type
|
57
|
+
type: klass.type
|
75
58
|
)
|
76
59
|
rescue ArgumentError
|
77
60
|
nil
|
data/lib/mihari/version.rb
CHANGED