mihari 5.6.1 → 5.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -1
- data/README.md +1 -0
- data/config.ru +1 -1
- data/docs/analyzers/fofa.md +31 -0
- data/docs/analyzers/index.md +1 -0
- data/frontend/package-lock.json +183 -186
- data/frontend/package.json +10 -10
- data/frontend/src/components/alert/Form.vue +1 -14
- data/frontend/src/components/artifact/AS.vue +2 -8
- data/frontend/src/components/artifact/DnsRecords.vue +2 -8
- data/frontend/src/components/artifact/ReverseDnsNames.vue +2 -10
- data/frontend/src/components/artifact/WhoisRecord.vue +1 -1
- data/lib/mihari/{base.rb → actor.rb} +27 -3
- data/lib/mihari/analyzers/base.rb +16 -20
- data/lib/mihari/analyzers/binaryedge.rb +4 -1
- data/lib/mihari/analyzers/censys.rb +5 -3
- data/lib/mihari/analyzers/circl.rb +4 -1
- data/lib/mihari/analyzers/crtsh.rb +4 -1
- data/lib/mihari/analyzers/dnstwister.rb +4 -1
- data/lib/mihari/analyzers/feed.rb +3 -0
- data/lib/mihari/analyzers/fofa.rb +65 -0
- data/lib/mihari/analyzers/greynoise.rb +4 -1
- data/lib/mihari/analyzers/hunterhow.rb +7 -2
- data/lib/mihari/analyzers/onyphe.rb +4 -1
- data/lib/mihari/analyzers/otx.rb +4 -1
- data/lib/mihari/analyzers/passivetotal.rb +5 -2
- data/lib/mihari/analyzers/pulsedive.rb +4 -1
- data/lib/mihari/analyzers/securitytrails.rb +5 -2
- data/lib/mihari/analyzers/shodan.rb +4 -1
- data/lib/mihari/analyzers/urlscan.rb +5 -2
- data/lib/mihari/analyzers/virustotal.rb +9 -6
- data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
- data/lib/mihari/analyzers/zoomeye.rb +8 -5
- data/lib/mihari/cli/alert.rb +3 -0
- data/lib/mihari/cli/base.rb +3 -0
- data/lib/mihari/cli/database.rb +3 -0
- data/lib/mihari/cli/main.rb +3 -0
- data/lib/mihari/cli/rule.rb +3 -0
- data/lib/mihari/clients/base.rb +3 -0
- data/lib/mihari/clients/binaryedge.rb +5 -2
- data/lib/mihari/clients/censys.rb +7 -4
- data/lib/mihari/clients/circl.rb +3 -0
- data/lib/mihari/clients/crtsh.rb +5 -2
- data/lib/mihari/clients/dnstwister.rb +3 -0
- data/lib/mihari/clients/fofa.rb +83 -0
- data/lib/mihari/clients/greynoise.rb +5 -2
- data/lib/mihari/clients/hunterhow.rb +5 -2
- data/lib/mihari/clients/misp.rb +3 -0
- data/lib/mihari/clients/onyphe.rb +5 -2
- data/lib/mihari/clients/otx.rb +3 -0
- data/lib/mihari/clients/passivetotal.rb +7 -4
- data/lib/mihari/clients/publsedive.rb +4 -1
- data/lib/mihari/clients/securitytrails.rb +6 -3
- data/lib/mihari/clients/shodan.rb +5 -2
- data/lib/mihari/clients/the_hive.rb +3 -0
- data/lib/mihari/clients/urlscan.rb +7 -4
- data/lib/mihari/clients/virustotal.rb +5 -2
- data/lib/mihari/clients/zoomeye.rb +3 -0
- data/lib/mihari/commands/alert.rb +5 -14
- data/lib/mihari/commands/database.rb +3 -0
- data/lib/mihari/commands/rule.rb +11 -11
- data/lib/mihari/commands/search.rb +9 -6
- data/lib/mihari/commands/version.rb +3 -0
- data/lib/mihari/commands/web.rb +4 -1
- data/lib/mihari/config.rb +139 -150
- data/lib/mihari/constants.rb +1 -1
- data/lib/mihari/database.rb +6 -0
- data/lib/mihari/emitters/base.rb +16 -25
- data/lib/mihari/emitters/database.rb +10 -9
- data/lib/mihari/emitters/misp.rb +20 -41
- data/lib/mihari/emitters/slack.rb +16 -13
- data/lib/mihari/emitters/the_hive.rb +18 -46
- data/lib/mihari/emitters/webhook.rb +34 -23
- data/lib/mihari/enrichers/base.rb +16 -15
- data/lib/mihari/enrichers/google_public_dns.rb +6 -5
- data/lib/mihari/enrichers/ipinfo.rb +10 -8
- data/lib/mihari/enrichers/shodan.rb +4 -6
- data/lib/mihari/enrichers/whois.rb +13 -10
- data/lib/mihari/errors.rb +6 -0
- data/lib/mihari/feed/parser.rb +3 -0
- data/lib/mihari/feed/reader.rb +3 -0
- data/lib/mihari/http.rb +6 -0
- data/lib/mihari/mixins/autonomous_system.rb +3 -0
- data/lib/mihari/mixins/configurable.rb +3 -0
- data/lib/mihari/mixins/error_notification.rb +3 -0
- data/lib/mihari/mixins/falsepositive.rb +3 -0
- data/lib/mihari/mixins/refang.rb +3 -0
- data/lib/mihari/mixins/retriable.rb +6 -2
- data/lib/mihari/models/alert.rb +78 -73
- data/lib/mihari/models/artifact.rb +186 -178
- data/lib/mihari/models/autonomous_system.rb +25 -20
- data/lib/mihari/models/cpe.rb +24 -19
- data/lib/mihari/models/dns.rb +27 -22
- data/lib/mihari/models/geolocation.rb +25 -20
- data/lib/mihari/models/port.rb +24 -19
- data/lib/mihari/models/reverse_dns.rb +24 -19
- data/lib/mihari/models/rule.rb +71 -66
- data/lib/mihari/models/tag.rb +8 -3
- data/lib/mihari/models/tagging.rb +8 -3
- data/lib/mihari/models/whois.rb +20 -17
- data/lib/mihari/rule.rb +357 -0
- data/lib/mihari/schemas/alert.rb +3 -0
- data/lib/mihari/schemas/analyzer.rb +105 -87
- data/lib/mihari/schemas/emitter.rb +12 -5
- data/lib/mihari/schemas/enricher.rb +11 -4
- data/lib/mihari/schemas/macros.rb +4 -0
- data/lib/mihari/schemas/mixins.rb +20 -0
- data/lib/mihari/schemas/rule.rb +6 -10
- data/lib/mihari/service.rb +16 -0
- data/lib/mihari/services/alert_builder.rb +8 -5
- data/lib/mihari/services/alert_proxy.rb +16 -7
- data/lib/mihari/services/alert_runner.rb +10 -14
- data/lib/mihari/services/rule_builder.rb +10 -7
- data/lib/mihari/services/rule_runner.rb +11 -13
- data/lib/mihari/structs/binaryedge.rb +14 -29
- data/lib/mihari/structs/censys.rb +54 -133
- data/lib/mihari/structs/config.rb +20 -31
- data/lib/mihari/structs/filters.rb +38 -0
- data/lib/mihari/structs/fofa.rb +44 -0
- data/lib/mihari/structs/google_public_dns.rb +10 -28
- data/lib/mihari/structs/greynoise.rb +38 -89
- data/lib/mihari/structs/hunterhow.rb +27 -25
- data/lib/mihari/structs/ipinfo.rb +14 -35
- data/lib/mihari/structs/onyphe.rb +36 -81
- data/lib/mihari/structs/shodan.rb +53 -118
- data/lib/mihari/structs/urlscan.rb +27 -66
- data/lib/mihari/structs/virustotal_intelligence.rb +23 -59
- data/lib/mihari/type_checker.rb +4 -0
- data/lib/mihari/types.rb +3 -0
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/api.rb +15 -10
- data/lib/mihari/web/app.rb +59 -54
- data/lib/mihari/web/endpoints/alerts.rb +94 -89
- data/lib/mihari/web/endpoints/artifacts.rb +115 -110
- data/lib/mihari/web/endpoints/configs.rb +18 -13
- data/lib/mihari/web/endpoints/ip_addresses.rb +21 -16
- data/lib/mihari/web/endpoints/rules.rb +202 -204
- data/lib/mihari/web/endpoints/tags.rb +41 -36
- data/lib/mihari/web/middleware/connection_adapter.rb +16 -9
- data/lib/mihari/web/middleware/error_notification_adapter.rb +17 -10
- data/lib/mihari/web/public/assets/{index-9cc489e6.js → index-821134e2.js} +54 -54
- data/lib/mihari/web/public/assets/mode-yaml-24faa242.js +8 -0
- data/lib/mihari/web/public/index.html +1 -1
- data/lib/mihari.rb +30 -13
- data/mihari.gemspec +9 -3
- data/mkdocs.yml +3 -2
- data/requirements.txt +1 -1
- metadata +44 -26
- data/lib/mihari/analyzers/rule.rb +0 -232
- data/lib/mihari/services/rule_proxy.rb +0 -182
- data/lib/mihari/templates/rule.yml.erb +0 -5
- data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
@@ -0,0 +1,8 @@
|
|
1
|
+
ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w[^\s:]*?)(:(?=\s|$))/},{token:["meta.tag","keyword"],regex:/(\w[^\s:]*?)(\s*:(?=\s|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:/[|>][-+\d]*(?:$|\s+(?:$|#))/,onMatch:function(e,t,n,r){r=r.replace(/ #.*/,"");var i=/^ *((:\s*)?-(\s*[^|>])?)?/.exec(r)[0].replace(/\S\s*$/,"").length,s=parseInt(/\d+[\s+-]*$/.exec(r));return s?(i+=s-1,this.next="mlString"):this.next="mlStringPre",n.length?(n[0]=this.next,n[1]=i):(n.push(this.next),n.push(i)),this.token},next:"mlString"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)(?=[^\d-\w]|$)$/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"\\b(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:/[^\s,:\[\]\{\}]+/}],mlStringPre:[{token:"indent",regex:/^ *$/},{token:"indent",regex:/^ */,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.shift(),n.shift()):(n[1]=e.length-1,this.next=n[0]="mlString"),this.token},next:"mlString"},{defaultToken:"string"}],mlString:[{token:"indent",regex:/^ *$/},{token:"indent",regex:/^ */,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.splice(0)):this.next="mlString",this.token},next:"mlString"},{token:"string",regex:".+"}]},this.normalizeRules()};r.inherits(s,i),t.YamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.commentBlock=function(e,t){var n=/\S/,r=e.getLine(t),i=r.search(n);if(i==-1||r[i]!="#")return;var o=r.length,u=e.getLength(),a=t,f=t;while(++t<u){r=e.getLine(t);var l=r.search(n);if(l==-1)continue;if(r[l]!="#")break;f=t}if(f>a){var c=e.getLine(f).length;return new s(a,o,f,c)}},this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;r=this.commentBlock(e,n);if(r)return r},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?"start":"","";if(u==-1){if(i==a&&r[i]=="#"&&s[i]=="#")return e.foldWidgets[n-1]="",e.foldWidgets[n+1]="","start"}else if(u==i&&r[i]=="#"&&o[i]=="#"&&e.getLine(n-2).search(/\S/)==-1)return e.foldWidgets[n-1]="start",e.foldWidgets[n+1]="","";return u!=-1&&u<i?e.foldWidgets[n-1]="start":e.foldWidgets[n-1]="",i<a?"start":""}}.call(o.prototype)}),ace.define("ace/mode/folding/yaml",["require","exports","module","ace/lib/oop","ace/mode/folding/coffee","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./coffee").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=/\S/,i=e.getLine(n),o=i.search(r),u=i[o]==="#",a=i[o]==="-";if(o==-1)return;var f=i.length,l=e.getLength(),c=n,h=n;if(u){var p=this.commentBlock(e,n);if(p)return p}else if(a){var p=this.indentationBlock(e,n);if(p)return p}else while(++n<l){var i=e.getLine(n),d=i.search(r);if(d==-1)continue;if(d<=o&&i[o]!=="-"){var v=e.getTokenAt(n,0);if(!v||v.type!=="string")break}h=n}if(h>c){var m=e.getLine(h).length;return new s(c,f,h,m)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/),f=r[i]==="-";if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?"start":"","";if(u==-1){if(i==a&&r[i]=="#"&&s[i]=="#")return e.foldWidgets[n-1]="",e.foldWidgets[n+1]="","start"}else if(u==i&&r[i]=="#"&&o[i]=="#"&&e.getLine(n-2).search(/\S/)==-1)return e.foldWidgets[n-1]="start",e.foldWidgets[n+1]="","";return u!=-1&&u<i?e.foldWidgets[n-1]="start":u!=-1&&u==i&&f?e.foldWidgets[n-1]="start":e.foldWidgets[n-1]="",i<a?"start":""}}.call(o.prototype)}),ace.define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/yaml","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./yaml_highlight_rules").YamlHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./folding/yaml").FoldMode,a=e("../worker/worker_client").WorkerClient,f=function(){this.HighlightRules=s,this.$outdent=new o,this.foldingRules=new u,this.$behaviour=this.$defaultBehaviour};r.inherits(f,i),function(){this.lineCommentStart=["#"],this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/yaml_worker","YamlWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/yaml"}.call(f.prototype),t.Mode=f}); (function() {
|
2
|
+
ace.require(["ace/mode/yaml"], function(m) {
|
3
|
+
if (typeof module == "object" && typeof exports == "object" && module) {
|
4
|
+
module.exports = m;
|
5
|
+
}
|
6
|
+
});
|
7
|
+
})();
|
8
|
+
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
7
7
|
<link rel="icon" href="/favicon.ico" />
|
8
8
|
<title>Mihari</title>
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
9
|
+
<script type="module" crossorigin src="/assets/index-821134e2.js"></script>
|
10
10
|
<link rel="stylesheet" href="/assets/index-56fc2187.css">
|
11
11
|
</head>
|
12
12
|
<body>
|
data/lib/mihari.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
# standard libs
|
4
4
|
require "ipaddr"
|
5
5
|
require "json"
|
6
|
-
require "net/http"
|
7
|
-
require "net/https"
|
8
6
|
require "resolv"
|
9
7
|
require "yaml"
|
10
8
|
|
@@ -35,7 +33,6 @@ require "addressable/uri"
|
|
35
33
|
require "awrence"
|
36
34
|
require "email_address"
|
37
35
|
require "memist"
|
38
|
-
require "net/ping"
|
39
36
|
require "parallel"
|
40
37
|
require "plissken"
|
41
38
|
require "public_suffix"
|
@@ -60,52 +57,67 @@ require "mihari/mixins/error_notification"
|
|
60
57
|
require "mihari/mixins/refang"
|
61
58
|
require "mihari/mixins/retriable"
|
62
59
|
|
60
|
+
#
|
61
|
+
# Mihari module
|
62
|
+
#
|
63
63
|
module Mihari
|
64
64
|
class << self
|
65
65
|
include Memist::Memoizable
|
66
66
|
|
67
|
+
#
|
68
|
+
# @return [Array<Mihari::Emitters::Base>]
|
69
|
+
#
|
67
70
|
def emitters
|
68
71
|
[]
|
69
72
|
end
|
70
73
|
memoize :emitters
|
71
74
|
|
72
75
|
#
|
73
|
-
# @return [Hash
|
76
|
+
# @return [Hash{String => Mihari::Enrichers::Base}]
|
74
77
|
#
|
75
78
|
def emitter_to_class
|
76
79
|
@emitter_to_class ||= emitters.flat_map do |klass|
|
77
|
-
klass.class_keys.map { |key| [key
|
80
|
+
klass.class_keys.map { |key| [key, klass] }
|
78
81
|
end.to_h
|
79
82
|
end
|
80
83
|
|
84
|
+
#
|
85
|
+
# @return [Array<Mihari::Analyzers::Base>]
|
86
|
+
#
|
81
87
|
def analyzers
|
82
88
|
[]
|
83
89
|
end
|
84
90
|
memoize :analyzers
|
85
91
|
|
86
92
|
#
|
87
|
-
# @return [Hash
|
93
|
+
# @return [Hash{String => Mihari::Analyzers::Base}]
|
88
94
|
#
|
89
95
|
def analyzer_to_class
|
90
96
|
@analyzer_to_class ||= analyzers.flat_map do |klass|
|
91
|
-
klass.class_keys.map { |key| [key
|
97
|
+
klass.class_keys.map { |key| [key, klass] }
|
92
98
|
end.to_h
|
93
99
|
end
|
94
100
|
|
101
|
+
#
|
102
|
+
# @return [Array<Mihari::Enrichers::Base>]
|
103
|
+
#
|
95
104
|
def enrichers
|
96
105
|
[]
|
97
106
|
end
|
98
107
|
memoize :enrichers
|
99
108
|
|
100
109
|
#
|
101
|
-
# @return [Hash
|
110
|
+
# @return [Hash{String => Mihari::Enrichers::Base}]
|
102
111
|
#
|
103
112
|
def enricher_to_class
|
104
113
|
@enricher_to_class ||= enrichers.flat_map do |klass|
|
105
|
-
klass.class_keys.map { |key| [key
|
114
|
+
klass.class_keys.map { |key| [key, klass] }
|
106
115
|
end.to_h
|
107
116
|
end
|
108
117
|
|
118
|
+
#
|
119
|
+
# @return [Mihari::Config]
|
120
|
+
#
|
109
121
|
def config
|
110
122
|
@config ||= Config.new
|
111
123
|
end
|
@@ -131,10 +143,14 @@ module Mihari
|
|
131
143
|
end
|
132
144
|
|
133
145
|
# Core classes
|
134
|
-
require "mihari/
|
146
|
+
require "mihari/service"
|
147
|
+
|
148
|
+
require "mihari/actor"
|
149
|
+
|
135
150
|
require "mihari/database"
|
136
151
|
require "mihari/http"
|
137
152
|
require "mihari/type_checker"
|
153
|
+
require "mihari/rule"
|
138
154
|
|
139
155
|
# Enrichers
|
140
156
|
require "mihari/enrichers/base"
|
@@ -174,6 +190,7 @@ require "mihari/clients/censys"
|
|
174
190
|
require "mihari/clients/circl"
|
175
191
|
require "mihari/clients/crtsh"
|
176
192
|
require "mihari/clients/dnstwister"
|
193
|
+
require "mihari/clients/fofa"
|
177
194
|
require "mihari/clients/greynoise"
|
178
195
|
require "mihari/clients/hunterhow"
|
179
196
|
require "mihari/clients/misp"
|
@@ -197,6 +214,7 @@ require "mihari/analyzers/circl"
|
|
197
214
|
require "mihari/analyzers/crtsh"
|
198
215
|
require "mihari/analyzers/dnstwister"
|
199
216
|
require "mihari/analyzers/feed"
|
217
|
+
require "mihari/analyzers/fofa"
|
200
218
|
require "mihari/analyzers/greynoise"
|
201
219
|
require "mihari/analyzers/hunterhow"
|
202
220
|
require "mihari/analyzers/onyphe"
|
@@ -210,8 +228,6 @@ require "mihari/analyzers/virustotal_intelligence"
|
|
210
228
|
require "mihari/analyzers/virustotal"
|
211
229
|
require "mihari/analyzers/zoomeye"
|
212
230
|
|
213
|
-
require "mihari/analyzers/rule"
|
214
|
-
|
215
231
|
# Types
|
216
232
|
require "mihari/types"
|
217
233
|
|
@@ -223,6 +239,7 @@ require "mihari/structs/binaryedge"
|
|
223
239
|
require "mihari/structs/censys"
|
224
240
|
require "mihari/structs/config"
|
225
241
|
require "mihari/structs/filters"
|
242
|
+
require "mihari/structs/fofa"
|
226
243
|
require "mihari/structs/google_public_dns"
|
227
244
|
require "mihari/structs/greynoise"
|
228
245
|
require "mihari/structs/ipinfo"
|
@@ -234,6 +251,7 @@ require "mihari/structs/virustotal_intelligence"
|
|
234
251
|
|
235
252
|
# Schemas
|
236
253
|
require "mihari/schemas/macros"
|
254
|
+
require "mihari/schemas/mixins"
|
237
255
|
|
238
256
|
require "mihari/schemas/options"
|
239
257
|
|
@@ -243,7 +261,6 @@ require "mihari/schemas/rule"
|
|
243
261
|
|
244
262
|
# Services
|
245
263
|
require "mihari/services/rule_builder"
|
246
|
-
require "mihari/services/rule_proxy"
|
247
264
|
require "mihari/services/rule_runner"
|
248
265
|
|
249
266
|
require "mihari/services/alert_builder"
|
data/mihari.gemspec
CHANGED
@@ -10,6 +10,10 @@ def ci_env?
|
|
10
10
|
ENV["CI"]
|
11
11
|
end
|
12
12
|
|
13
|
+
def is_ruby2?
|
14
|
+
RUBY_VERSION.to_s.start_with?("2.")
|
15
|
+
end
|
16
|
+
|
13
17
|
Gem::Specification.new do |spec|
|
14
18
|
spec.name = "mihari"
|
15
19
|
spec.version = Mihari::VERSION
|
@@ -48,7 +52,7 @@ Gem::Specification.new do |spec|
|
|
48
52
|
spec.add_development_dependency "rb-fsevent", "~> 0.11"
|
49
53
|
spec.add_development_dependency "rerun", "~> 0.14"
|
50
54
|
spec.add_development_dependency "rspec", "~> 3.12"
|
51
|
-
spec.add_development_dependency "rubocop-rspec", "~> 2.
|
55
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.25"
|
52
56
|
spec.add_development_dependency "simplecov-lcov", "~> 0.8"
|
53
57
|
spec.add_development_dependency "standard", "~> 1.31"
|
54
58
|
spec.add_development_dependency "test-prof", "~> 1.2"
|
@@ -56,6 +60,8 @@ Gem::Specification.new do |spec|
|
|
56
60
|
spec.add_development_dependency "vcr", "~> 6.2"
|
57
61
|
spec.add_development_dependency "webmock", "~> 3.19"
|
58
62
|
|
63
|
+
spec.add_development_dependency "rubocop-yard", "~> 0.7" unless is_ruby2?
|
64
|
+
|
59
65
|
unless ci_env?
|
60
66
|
spec.add_development_dependency "lefthook", "~> 1.5"
|
61
67
|
spec.add_development_dependency "solargraph", "~> 0.49"
|
@@ -63,6 +69,7 @@ Gem::Specification.new do |spec|
|
|
63
69
|
|
64
70
|
spec.add_dependency "activerecord", "7.1.1"
|
65
71
|
spec.add_dependency "addressable", "2.8.5"
|
72
|
+
spec.add_dependency "anyway_config", "2.5.4"
|
66
73
|
spec.add_dependency "awrence", "2.0.1"
|
67
74
|
spec.add_dependency "dotenv", "2.8.1"
|
68
75
|
spec.add_dependency "dry-container", "0.11.0"
|
@@ -80,7 +87,6 @@ Gem::Specification.new do |spec|
|
|
80
87
|
spec.add_dependency "jr-cli", "0.6.0"
|
81
88
|
spec.add_dependency "launchy", "2.5.2"
|
82
89
|
spec.add_dependency "memist", "2.0.2"
|
83
|
-
spec.add_dependency "net-ping", "2.0.8"
|
84
90
|
spec.add_dependency "normalize_country", "0.3.2"
|
85
91
|
spec.add_dependency "parallel", "1.23.0"
|
86
92
|
spec.add_dependency "plissken", "2.0.1"
|
@@ -92,7 +98,7 @@ Gem::Specification.new do |spec|
|
|
92
98
|
spec.add_dependency "semantic_logger", "4.14.0"
|
93
99
|
spec.add_dependency "sentry-ruby", "5.12.0"
|
94
100
|
spec.add_dependency "slack-notifier", "2.4.0"
|
95
|
-
spec.add_dependency "sqlite3", "1.6.
|
101
|
+
spec.add_dependency "sqlite3", "1.6.8"
|
96
102
|
spec.add_dependency "thor", "1.3.0"
|
97
103
|
spec.add_dependency "thor-hollaback", "0.2.1"
|
98
104
|
spec.add_dependency "uuidtools", "2.2.0"
|
data/mkdocs.yml
CHANGED
data/requirements.txt
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
mkdocs==1.5.3
|
2
|
-
mkdocs-material==9.4.
|
2
|
+
mkdocs-material==9.4.7
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mihari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: '2.
|
187
|
+
version: '2.25'
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version: '2.
|
194
|
+
version: '2.25'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: simplecov-lcov
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,6 +276,20 @@ dependencies:
|
|
276
276
|
- - "~>"
|
277
277
|
- !ruby/object:Gem::Version
|
278
278
|
version: '3.19'
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: rubocop-yard
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - "~>"
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '0.7'
|
286
|
+
type: :development
|
287
|
+
prerelease: false
|
288
|
+
version_requirements: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - "~>"
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: '0.7'
|
279
293
|
- !ruby/object:Gem::Dependency
|
280
294
|
name: lefthook
|
281
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -332,6 +346,20 @@ dependencies:
|
|
332
346
|
- - '='
|
333
347
|
- !ruby/object:Gem::Version
|
334
348
|
version: 2.8.5
|
349
|
+
- !ruby/object:Gem::Dependency
|
350
|
+
name: anyway_config
|
351
|
+
requirement: !ruby/object:Gem::Requirement
|
352
|
+
requirements:
|
353
|
+
- - '='
|
354
|
+
- !ruby/object:Gem::Version
|
355
|
+
version: 2.5.4
|
356
|
+
type: :runtime
|
357
|
+
prerelease: false
|
358
|
+
version_requirements: !ruby/object:Gem::Requirement
|
359
|
+
requirements:
|
360
|
+
- - '='
|
361
|
+
- !ruby/object:Gem::Version
|
362
|
+
version: 2.5.4
|
335
363
|
- !ruby/object:Gem::Dependency
|
336
364
|
name: awrence
|
337
365
|
requirement: !ruby/object:Gem::Requirement
|
@@ -570,20 +598,6 @@ dependencies:
|
|
570
598
|
- - '='
|
571
599
|
- !ruby/object:Gem::Version
|
572
600
|
version: 2.0.2
|
573
|
-
- !ruby/object:Gem::Dependency
|
574
|
-
name: net-ping
|
575
|
-
requirement: !ruby/object:Gem::Requirement
|
576
|
-
requirements:
|
577
|
-
- - '='
|
578
|
-
- !ruby/object:Gem::Version
|
579
|
-
version: 2.0.8
|
580
|
-
type: :runtime
|
581
|
-
prerelease: false
|
582
|
-
version_requirements: !ruby/object:Gem::Requirement
|
583
|
-
requirements:
|
584
|
-
- - '='
|
585
|
-
- !ruby/object:Gem::Version
|
586
|
-
version: 2.0.8
|
587
601
|
- !ruby/object:Gem::Dependency
|
588
602
|
name: normalize_country
|
589
603
|
requirement: !ruby/object:Gem::Requirement
|
@@ -744,14 +758,14 @@ dependencies:
|
|
744
758
|
requirements:
|
745
759
|
- - '='
|
746
760
|
- !ruby/object:Gem::Version
|
747
|
-
version: 1.6.
|
761
|
+
version: 1.6.8
|
748
762
|
type: :runtime
|
749
763
|
prerelease: false
|
750
764
|
version_requirements: !ruby/object:Gem::Requirement
|
751
765
|
requirements:
|
752
766
|
- - '='
|
753
767
|
- !ruby/object:Gem::Version
|
754
|
-
version: 1.6.
|
768
|
+
version: 1.6.8
|
755
769
|
- !ruby/object:Gem::Dependency
|
756
770
|
name: thor
|
757
771
|
requirement: !ruby/object:Gem::Requirement
|
@@ -849,6 +863,7 @@ files:
|
|
849
863
|
- docs/analyzers/crtsh.md
|
850
864
|
- docs/analyzers/dnstwister.md
|
851
865
|
- docs/analyzers/feed.md
|
866
|
+
- docs/analyzers/fofa.md
|
852
867
|
- docs/analyzers/greynoise.md
|
853
868
|
- docs/analyzers/hunterhow.md
|
854
869
|
- docs/analyzers/index.md
|
@@ -970,6 +985,7 @@ files:
|
|
970
985
|
- frontend/vitest.config.ts
|
971
986
|
- lefthook.yml
|
972
987
|
- lib/mihari.rb
|
988
|
+
- lib/mihari/actor.rb
|
973
989
|
- lib/mihari/analyzers/base.rb
|
974
990
|
- lib/mihari/analyzers/binaryedge.rb
|
975
991
|
- lib/mihari/analyzers/censys.rb
|
@@ -977,20 +993,19 @@ files:
|
|
977
993
|
- lib/mihari/analyzers/crtsh.rb
|
978
994
|
- lib/mihari/analyzers/dnstwister.rb
|
979
995
|
- lib/mihari/analyzers/feed.rb
|
996
|
+
- lib/mihari/analyzers/fofa.rb
|
980
997
|
- lib/mihari/analyzers/greynoise.rb
|
981
998
|
- lib/mihari/analyzers/hunterhow.rb
|
982
999
|
- lib/mihari/analyzers/onyphe.rb
|
983
1000
|
- lib/mihari/analyzers/otx.rb
|
984
1001
|
- lib/mihari/analyzers/passivetotal.rb
|
985
1002
|
- lib/mihari/analyzers/pulsedive.rb
|
986
|
-
- lib/mihari/analyzers/rule.rb
|
987
1003
|
- lib/mihari/analyzers/securitytrails.rb
|
988
1004
|
- lib/mihari/analyzers/shodan.rb
|
989
1005
|
- lib/mihari/analyzers/urlscan.rb
|
990
1006
|
- lib/mihari/analyzers/virustotal.rb
|
991
1007
|
- lib/mihari/analyzers/virustotal_intelligence.rb
|
992
1008
|
- lib/mihari/analyzers/zoomeye.rb
|
993
|
-
- lib/mihari/base.rb
|
994
1009
|
- lib/mihari/cli/alert.rb
|
995
1010
|
- lib/mihari/cli/base.rb
|
996
1011
|
- lib/mihari/cli/database.rb
|
@@ -1002,6 +1017,7 @@ files:
|
|
1002
1017
|
- lib/mihari/clients/circl.rb
|
1003
1018
|
- lib/mihari/clients/crtsh.rb
|
1004
1019
|
- lib/mihari/clients/dnstwister.rb
|
1020
|
+
- lib/mihari/clients/fofa.rb
|
1005
1021
|
- lib/mihari/clients/greynoise.rb
|
1006
1022
|
- lib/mihari/clients/hunterhow.rb
|
1007
1023
|
- lib/mihari/clients/misp.rb
|
@@ -1071,23 +1087,26 @@ files:
|
|
1071
1087
|
- lib/mihari/models/tag.rb
|
1072
1088
|
- lib/mihari/models/tagging.rb
|
1073
1089
|
- lib/mihari/models/whois.rb
|
1090
|
+
- lib/mihari/rule.rb
|
1074
1091
|
- lib/mihari/schemas/alert.rb
|
1075
1092
|
- lib/mihari/schemas/analyzer.rb
|
1076
1093
|
- lib/mihari/schemas/emitter.rb
|
1077
1094
|
- lib/mihari/schemas/enricher.rb
|
1078
1095
|
- lib/mihari/schemas/macros.rb
|
1096
|
+
- lib/mihari/schemas/mixins.rb
|
1079
1097
|
- lib/mihari/schemas/options.rb
|
1080
1098
|
- lib/mihari/schemas/rule.rb
|
1099
|
+
- lib/mihari/service.rb
|
1081
1100
|
- lib/mihari/services/alert_builder.rb
|
1082
1101
|
- lib/mihari/services/alert_proxy.rb
|
1083
1102
|
- lib/mihari/services/alert_runner.rb
|
1084
1103
|
- lib/mihari/services/rule_builder.rb
|
1085
|
-
- lib/mihari/services/rule_proxy.rb
|
1086
1104
|
- lib/mihari/services/rule_runner.rb
|
1087
1105
|
- lib/mihari/structs/binaryedge.rb
|
1088
1106
|
- lib/mihari/structs/censys.rb
|
1089
1107
|
- lib/mihari/structs/config.rb
|
1090
1108
|
- lib/mihari/structs/filters.rb
|
1109
|
+
- lib/mihari/structs/fofa.rb
|
1091
1110
|
- lib/mihari/structs/google_public_dns.rb
|
1092
1111
|
- lib/mihari/structs/greynoise.rb
|
1093
1112
|
- lib/mihari/structs/hunterhow.rb
|
@@ -1096,7 +1115,6 @@ files:
|
|
1096
1115
|
- lib/mihari/structs/shodan.rb
|
1097
1116
|
- lib/mihari/structs/urlscan.rb
|
1098
1117
|
- lib/mihari/structs/virustotal_intelligence.rb
|
1099
|
-
- lib/mihari/templates/rule.yml.erb
|
1100
1118
|
- lib/mihari/type_checker.rb
|
1101
1119
|
- lib/mihari/types.rb
|
1102
1120
|
- lib/mihari/version.rb
|
@@ -1111,8 +1129,8 @@ files:
|
|
1111
1129
|
- lib/mihari/web/middleware/connection_adapter.rb
|
1112
1130
|
- lib/mihari/web/middleware/error_notification_adapter.rb
|
1113
1131
|
- lib/mihari/web/public/assets/index-56fc2187.css
|
1114
|
-
- lib/mihari/web/public/assets/index-
|
1115
|
-
- lib/mihari/web/public/assets/mode-yaml-
|
1132
|
+
- lib/mihari/web/public/assets/index-821134e2.js
|
1133
|
+
- lib/mihari/web/public/assets/mode-yaml-24faa242.js
|
1116
1134
|
- lib/mihari/web/public/favicon.ico
|
1117
1135
|
- lib/mihari/web/public/index.html
|
1118
1136
|
- lib/mihari/web/public/redoc-static.html
|
@@ -1,232 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mihari
|
4
|
-
module Analyzers
|
5
|
-
class Rule
|
6
|
-
include Mixins::FalsePositive
|
7
|
-
|
8
|
-
# @return [Mihari::Services::RuleProxy]
|
9
|
-
attr_reader :rule
|
10
|
-
|
11
|
-
# @return [Time]
|
12
|
-
attr_reader :base_time
|
13
|
-
|
14
|
-
#
|
15
|
-
# @param [Mihari::Services::RuleProxy] rule
|
16
|
-
#
|
17
|
-
def initialize(rule)
|
18
|
-
@rule = rule
|
19
|
-
@base_time = Time.now.utc
|
20
|
-
|
21
|
-
validate_analyzer_configurations
|
22
|
-
end
|
23
|
-
|
24
|
-
#
|
25
|
-
# Returns a list of artifacts matched with queries/analyzers (with the rule ID)
|
26
|
-
#
|
27
|
-
# @return [Array<Mihari::Artifact>]
|
28
|
-
#
|
29
|
-
def artifacts
|
30
|
-
analyzers.flat_map do |analyzer|
|
31
|
-
result = analyzer.result
|
32
|
-
|
33
|
-
raise result.failure if result.failure? && !analyzer.ignore_error?
|
34
|
-
|
35
|
-
artifacts = result.value!
|
36
|
-
artifacts.map do |artifact|
|
37
|
-
artifact.rule_id = rule.id
|
38
|
-
artifact
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# Normalize artifacts
|
45
|
-
# - Reject invalid artifacts (for just in case)
|
46
|
-
# - Select artifacts with allowed data types
|
47
|
-
# - Reject artifacts with false positive values
|
48
|
-
# - Set rule ID
|
49
|
-
#
|
50
|
-
# @return [Array<Mihari::Artifact>]
|
51
|
-
#
|
52
|
-
def normalized_artifacts
|
53
|
-
valid_artifacts = artifacts.uniq(&:data).select(&:valid?)
|
54
|
-
date_type_allowed_artifacts = valid_artifacts.select { |artifact| rule.data_types.include? artifact.data_type }
|
55
|
-
date_type_allowed_artifacts.reject { |artifact| falsepositive? artifact.data }
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
# Uniquify artifacts (assure rule level uniqueness)
|
60
|
-
#
|
61
|
-
# @return [Array<Mihari::Artifact>]
|
62
|
-
#
|
63
|
-
def unique_artifacts
|
64
|
-
normalized_artifacts.select do |artifact|
|
65
|
-
artifact.unique?(base_time: base_time, artifact_lifetime: rule.artifact_lifetime)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# Enriched artifacts
|
71
|
-
#
|
72
|
-
# @return [Array<Mihari::Artifact>]
|
73
|
-
#
|
74
|
-
def enriched_artifacts
|
75
|
-
@enriched_artifacts ||= Parallel.map(unique_artifacts) do |artifact|
|
76
|
-
enrichers.each { |enricher| artifact.enrich_by_enricher enricher }
|
77
|
-
artifact
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
#
|
82
|
-
# Bulk emit
|
83
|
-
#
|
84
|
-
# @return [Array<Mihari::Alert>]
|
85
|
-
#
|
86
|
-
def bulk_emit
|
87
|
-
return [] if enriched_artifacts.empty?
|
88
|
-
|
89
|
-
# NOTE: separate parallel execution and logging
|
90
|
-
# because the logger does not work along with Parallel
|
91
|
-
results = Parallel.map(valid_emitters) do |emitter|
|
92
|
-
emitter.result
|
93
|
-
end
|
94
|
-
|
95
|
-
results.zip(valid_emitters).map do |result_and_emitter|
|
96
|
-
result, emitter = result_and_emitter
|
97
|
-
|
98
|
-
Mihari.logger.info "Emission by #{emitter.class} is failed: #{result.failure}" if result.failure?
|
99
|
-
Mihari.logger.info "Emission by #{emitter.class} is succeeded" if result.success?
|
100
|
-
|
101
|
-
result.value_or nil
|
102
|
-
end.compact
|
103
|
-
end
|
104
|
-
|
105
|
-
#
|
106
|
-
# Set artifacts & run emitters in parallel
|
107
|
-
#
|
108
|
-
# @return [Mihari::Alert, nil]
|
109
|
-
#
|
110
|
-
def run
|
111
|
-
alert_or_something = bulk_emit
|
112
|
-
# returns Mihari::Alert created by the database emitter
|
113
|
-
alert_or_something.find { |res| res.is_a?(Mihari::Alert) }
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
#
|
119
|
-
# Check whether a value is a falsepositive value or not
|
120
|
-
#
|
121
|
-
# @return [Boolean]
|
122
|
-
#
|
123
|
-
def falsepositive?(value)
|
124
|
-
return true if rule.falsepositives.include?(value)
|
125
|
-
|
126
|
-
regexps = rule.falsepositives.select { |fp| fp.is_a?(Regexp) }
|
127
|
-
regexps.any? { |fp| fp.match?(value) }
|
128
|
-
end
|
129
|
-
|
130
|
-
#
|
131
|
-
# Get analyzer class
|
132
|
-
#
|
133
|
-
# @param [String] key
|
134
|
-
#
|
135
|
-
# @return [Class<Mihari::Analyzers::Base>] analyzer class
|
136
|
-
#
|
137
|
-
def get_analyzer_class(key)
|
138
|
-
raise ArgumentError, "#{key} is not supported" unless Mihari.analyzer_to_class.key?(key)
|
139
|
-
|
140
|
-
Mihari.analyzer_to_class[key]
|
141
|
-
end
|
142
|
-
|
143
|
-
#
|
144
|
-
# @return [Array<Mihari::Analyzers::Base>]
|
145
|
-
#
|
146
|
-
def analyzers
|
147
|
-
rule.queries.map do |query_params|
|
148
|
-
analyzer_name = query_params[:analyzer]
|
149
|
-
klass = get_analyzer_class(analyzer_name)
|
150
|
-
klass.from_query(query_params)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
#
|
155
|
-
# Get emitter class
|
156
|
-
#
|
157
|
-
# @param [String] key
|
158
|
-
#
|
159
|
-
# @return [Class<Mihari::Emitters::Base>] emitter class
|
160
|
-
#
|
161
|
-
def get_emitter_class(key)
|
162
|
-
raise ArgumentError, "#{key} is not supported" unless Mihari.emitter_to_class.key?(key)
|
163
|
-
|
164
|
-
Mihari.emitter_to_class[key]
|
165
|
-
end
|
166
|
-
|
167
|
-
#
|
168
|
-
# @return [Array<Mihari::Emitters::Base>]
|
169
|
-
#
|
170
|
-
def emitters
|
171
|
-
rule.emitters.map(&:deep_dup).map do |params|
|
172
|
-
name = params[:emitter]
|
173
|
-
options = params[:options]
|
174
|
-
|
175
|
-
%i[emitter options].each { |key| params.delete key }
|
176
|
-
|
177
|
-
klass = get_emitter_class(name)
|
178
|
-
klass.new(artifacts: enriched_artifacts, rule: rule, options: options, **params)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
#
|
183
|
-
# @return [Array<Mihari::Emitters::Base>]
|
184
|
-
#
|
185
|
-
def valid_emitters
|
186
|
-
@valid_emitters ||= emitters.select(&:valid?)
|
187
|
-
end
|
188
|
-
|
189
|
-
#
|
190
|
-
# Get enricher class
|
191
|
-
#
|
192
|
-
# @param [String] key
|
193
|
-
#
|
194
|
-
# @return [Class<Mihari::Enrichers::Base>] enricher class
|
195
|
-
#
|
196
|
-
def get_enricher_class(key)
|
197
|
-
raise ArgumentError, "#{key} is not supported" unless Mihari.enricher_to_class.key?(key)
|
198
|
-
|
199
|
-
Mihari.enricher_to_class[key]
|
200
|
-
end
|
201
|
-
|
202
|
-
#
|
203
|
-
# @return [Array<Mihari::Enrichers::Base>] enrichers
|
204
|
-
#
|
205
|
-
def enrichers
|
206
|
-
@enrichers ||= rule.enrichers.map(&:deep_dup).map do |params|
|
207
|
-
name = params[:enricher]
|
208
|
-
options = params[:options]
|
209
|
-
|
210
|
-
%i[enricher options].each { |key| params.delete key }
|
211
|
-
|
212
|
-
klass = get_enricher_class(name)
|
213
|
-
klass.new(options: options, **params)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
#
|
218
|
-
# Validate configuration of analyzers
|
219
|
-
#
|
220
|
-
def validate_analyzer_configurations
|
221
|
-
analyzers.map do |analyzer|
|
222
|
-
next if analyzer.configured?
|
223
|
-
|
224
|
-
joined = analyzer.configuration_keys.join(", ")
|
225
|
-
be = (analyzer.configuration_keys.length > 1) ? "are" : "is"
|
226
|
-
message = "#{analyzer.class.class_key} is not configured correctly. #{joined} #{be} missing."
|
227
|
-
raise ConfigurationError, message
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|