mihari 5.6.2 → 5.7.1
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/lib/mihari/actor.rb +18 -2
- data/lib/mihari/analyzers/base.rb +13 -12
- data/lib/mihari/analyzers/binaryedge.rb +4 -1
- data/lib/mihari/analyzers/censys.rb +4 -2
- 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 +6 -1
- data/lib/mihari/analyzers/onyphe.rb +4 -1
- data/lib/mihari/analyzers/otx.rb +4 -1
- data/lib/mihari/analyzers/passivetotal.rb +4 -1
- data/lib/mihari/analyzers/pulsedive.rb +3 -0
- data/lib/mihari/analyzers/securitytrails.rb +4 -1
- data/lib/mihari/analyzers/shodan.rb +4 -1
- data/lib/mihari/analyzers/urlscan.rb +4 -1
- data/lib/mihari/analyzers/virustotal.rb +4 -1
- data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
- data/lib/mihari/analyzers/zoomeye.rb +5 -2
- 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 +3 -0
- 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 +3 -0
- data/lib/mihari/clients/publsedive.rb +4 -1
- data/lib/mihari/clients/securitytrails.rb +3 -0
- 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 +9 -16
- data/lib/mihari/commands/database.rb +3 -0
- data/lib/mihari/commands/rule.rb +10 -1
- data/lib/mihari/commands/search.rb +13 -29
- 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 +13 -11
- data/lib/mihari/emitters/database.rb +4 -1
- data/lib/mihari/emitters/misp.rb +7 -4
- data/lib/mihari/emitters/slack.rb +3 -3
- data/lib/mihari/emitters/the_hive.rb +3 -3
- data/lib/mihari/emitters/webhook.rb +4 -3
- data/lib/mihari/enrichers/base.rb +15 -9
- data/lib/mihari/enrichers/google_public_dns.rb +6 -5
- data/lib/mihari/enrichers/ipinfo.rb +11 -9
- data/lib/mihari/enrichers/shodan.rb +4 -6
- data/lib/mihari/enrichers/whois.rb +12 -9
- data/lib/mihari/entities/tag.rb +1 -0
- 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 +7 -4
- data/lib/mihari/models/artifact.rb +6 -0
- data/lib/mihari/models/autonomous_system.rb +4 -1
- data/lib/mihari/models/cpe.rb +4 -1
- data/lib/mihari/models/dns.rb +4 -1
- data/lib/mihari/models/geolocation.rb +4 -1
- data/lib/mihari/models/port.rb +4 -1
- data/lib/mihari/models/reverse_dns.rb +4 -1
- data/lib/mihari/models/rule.rb +6 -3
- data/lib/mihari/models/tag.rb +3 -0
- data/lib/mihari/models/tagging.rb +3 -0
- data/lib/mihari/models/whois.rb +4 -3
- data/lib/mihari/rule.rb +31 -12
- data/lib/mihari/schemas/alert.rb +3 -0
- data/lib/mihari/schemas/analyzer.rb +11 -0
- data/lib/mihari/schemas/emitter.rb +3 -0
- data/lib/mihari/schemas/enricher.rb +3 -0
- data/lib/mihari/schemas/macros.rb +4 -0
- data/lib/mihari/schemas/mixins.rb +5 -0
- data/lib/mihari/schemas/rule.rb +3 -0
- data/lib/mihari/service.rb +26 -0
- data/lib/mihari/services/alert_builder.rb +85 -9
- data/lib/mihari/services/alert_runner.rb +8 -19
- data/lib/mihari/services/rule_builder.rb +13 -12
- data/lib/mihari/services/rule_runner.rb +7 -32
- data/lib/mihari/structs/binaryedge.rb +22 -28
- data/lib/mihari/structs/censys.rb +48 -141
- data/lib/mihari/structs/config.rb +19 -30
- data/lib/mihari/structs/filters.rb +38 -0
- data/lib/mihari/structs/fofa.rb +47 -0
- data/lib/mihari/structs/google_public_dns.rb +10 -32
- data/lib/mihari/structs/greynoise.rb +33 -90
- data/lib/mihari/structs/hunterhow.rb +24 -28
- data/lib/mihari/structs/ipinfo.rb +14 -37
- data/lib/mihari/structs/onyphe.rb +31 -80
- data/lib/mihari/structs/shodan.rb +47 -114
- data/lib/mihari/structs/urlscan.rb +24 -69
- data/lib/mihari/structs/virustotal_intelligence.rb +20 -64
- 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 +64 -56
- data/lib/mihari/web/endpoints/alerts.rb +127 -85
- data/lib/mihari/web/endpoints/artifacts.rb +91 -79
- data/lib/mihari/web/endpoints/configs.rb +18 -13
- data/lib/mihari/web/endpoints/ip_addresses.rb +35 -15
- data/lib/mihari/web/endpoints/rules.rb +236 -187
- data/lib/mihari/web/endpoints/tags.rb +42 -35
- 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-28d4c79d.js → index-07fafab5.js} +31 -30
- 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 +24 -6
- data/mihari.gemspec +9 -2
- data/mkdocs.yml +4 -2
- metadata +38 -133
- data/docs/alternatives.md +0 -5
- data/docs/analyzers/binaryedge.md +0 -26
- data/docs/analyzers/censys.md +0 -31
- data/docs/analyzers/circl.md +0 -37
- data/docs/analyzers/crtsh.md +0 -26
- data/docs/analyzers/dnstwister.md +0 -25
- data/docs/analyzers/feed.md +0 -73
- data/docs/analyzers/greynoise.md +0 -26
- data/docs/analyzers/hunterhow.md +0 -33
- data/docs/analyzers/index.md +0 -103
- data/docs/analyzers/onyphe.md +0 -26
- data/docs/analyzers/otx.md +0 -28
- data/docs/analyzers/passivetotal.md +0 -52
- data/docs/analyzers/pulsedive.md +0 -28
- data/docs/analyzers/securitytrails.md +0 -41
- data/docs/analyzers/shodan.md +0 -26
- data/docs/analyzers/urlscan.md +0 -28
- data/docs/analyzers/virustotal.md +0 -43
- data/docs/analyzers/virustotal_intelligence.md +0 -33
- data/docs/analyzers/zoomeye.md +0 -38
- data/docs/configuration.md +0 -35
- data/docs/emitters/database.md +0 -22
- data/docs/emitters/hive.md +0 -26
- data/docs/emitters/index.md +0 -36
- data/docs/emitters/misp.md +0 -21
- data/docs/emitters/slack.md +0 -21
- data/docs/emitters/webhook.md +0 -63
- data/docs/enrichers/google_public_dns.md +0 -19
- data/docs/enrichers/index.md +0 -35
- data/docs/enrichers/ipinfo.md +0 -26
- data/docs/enrichers/shodan.md +0 -22
- data/docs/enrichers/whois.md +0 -17
- data/docs/github_actions.md +0 -43
- data/docs/index.md +0 -11
- data/docs/installation.md +0 -31
- data/docs/requirements.md +0 -13
- data/docs/rule.md +0 -168
- data/docs/tags.md +0 -3
- data/docs/usage.md +0 -103
- data/frontend/.eslintrc.cjs +0 -22
- data/frontend/.gitignore +0 -31
- data/frontend/.prettierrc.json +0 -8
- data/frontend/README.md +0 -3
- data/frontend/env.d.ts +0 -5
- data/frontend/index.html +0 -21
- data/frontend/package-lock.json +0 -7219
- data/frontend/package.json +0 -67
- data/frontend/public/favicon.ico +0 -0
- data/frontend/scripts/swagger_doc_to_yaml.rb +0 -23
- data/frontend/src/App.vue +0 -27
- data/frontend/src/ace-config.ts +0 -6
- data/frontend/src/api-helper.ts +0 -111
- data/frontend/src/api.ts +0 -105
- data/frontend/src/components/ErrorMessage.vue +0 -31
- data/frontend/src/components/Loading.vue +0 -15
- data/frontend/src/components/Navbar.vue +0 -42
- data/frontend/src/components/Pagination.vue +0 -119
- data/frontend/src/components/alert/Alert.vue +0 -87
- data/frontend/src/components/alert/Alerts.vue +0 -63
- data/frontend/src/components/alert/AlertsWithPagination.vue +0 -90
- data/frontend/src/components/alert/AlertsWrapper.vue +0 -128
- data/frontend/src/components/alert/Form.vue +0 -182
- data/frontend/src/components/artifact/AS.vue +0 -29
- data/frontend/src/components/artifact/Artifact.vue +0 -287
- data/frontend/src/components/artifact/ArtifactTag.vue +0 -64
- data/frontend/src/components/artifact/ArtifactTags.vue +0 -29
- data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -57
- data/frontend/src/components/artifact/CPEs.vue +0 -23
- data/frontend/src/components/artifact/DnsRecords.vue +0 -38
- data/frontend/src/components/artifact/Ports.vue +0 -23
- data/frontend/src/components/artifact/ReverseDnsNames.vue +0 -31
- data/frontend/src/components/artifact/Tags.vue +0 -29
- data/frontend/src/components/artifact/WhoisRecord.vue +0 -44
- data/frontend/src/components/config/Configs.vue +0 -65
- data/frontend/src/components/config/ConfigsWrapper.vue +0 -32
- data/frontend/src/components/link/Link.vue +0 -32
- data/frontend/src/components/link/Links.vue +0 -42
- data/frontend/src/components/rule/EditRule.vue +0 -72
- data/frontend/src/components/rule/EditRuleWrapper.vue +0 -48
- data/frontend/src/components/rule/Form.vue +0 -158
- data/frontend/src/components/rule/InputForm.vue +0 -45
- data/frontend/src/components/rule/NewRule.vue +0 -57
- data/frontend/src/components/rule/Rule.vue +0 -100
- data/frontend/src/components/rule/RuleWrapper.vue +0 -53
- data/frontend/src/components/rule/Rules.vue +0 -84
- data/frontend/src/components/rule/RulesWrapper.vue +0 -121
- data/frontend/src/components/rule/YAML.vue +0 -37
- data/frontend/src/components/tag/Tag.vue +0 -65
- data/frontend/src/components/tag/Tags.vue +0 -37
- data/frontend/src/countries.ts +0 -350
- data/frontend/src/index.ts +0 -20
- data/frontend/src/links/anyrun.ts +0 -19
- data/frontend/src/links/base.ts +0 -14
- data/frontend/src/links/censys.ts +0 -20
- data/frontend/src/links/crtsh.ts +0 -20
- data/frontend/src/links/dnslytics.ts +0 -38
- data/frontend/src/links/greynoise.ts +0 -20
- data/frontend/src/links/index.ts +0 -40
- data/frontend/src/links/intezer.ts +0 -20
- data/frontend/src/links/otx.ts +0 -33
- data/frontend/src/links/securitytrails.ts +0 -38
- data/frontend/src/links/shodan.ts +0 -20
- data/frontend/src/links/urlscan.ts +0 -50
- data/frontend/src/links/virustotal.ts +0 -72
- data/frontend/src/main.ts +0 -41
- data/frontend/src/router/index.ts +0 -57
- data/frontend/src/rule.ts +0 -14
- data/frontend/src/shims-vue.d.ts +0 -6
- data/frontend/src/swagger.yaml +0 -771
- data/frontend/src/types.ts +0 -188
- data/frontend/src/utils.ts +0 -54
- data/frontend/src/views/Alerts.vue +0 -20
- data/frontend/src/views/Artifact.vue +0 -39
- data/frontend/src/views/Configs.vue +0 -20
- data/frontend/src/views/EditRule.vue +0 -39
- data/frontend/src/views/NewRule.vue +0 -26
- data/frontend/src/views/Rule.vue +0 -39
- data/frontend/src/views/Rules.vue +0 -20
- data/frontend/tests/utils.spec.ts +0 -9
- data/frontend/tsconfig.app.json +0 -21
- data/frontend/tsconfig.json +0 -14
- data/frontend/tsconfig.node.json +0 -13
- data/frontend/tsconfig.vitest.json +0 -12
- data/frontend/vite.config.ts +0 -24
- data/frontend/vitest.config.ts +0 -21
- data/lib/mihari/services/alert_proxy.rb +0 -92
- data/lib/mihari/templates/rule.yml.erb +0 -5
- data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
data/frontend/src/types.ts
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
export interface Pagination {
|
2
|
-
total: number
|
3
|
-
currentPage: number
|
4
|
-
pageSize: number
|
5
|
-
}
|
6
|
-
|
7
|
-
export interface ConfigValue {
|
8
|
-
key: string
|
9
|
-
value: string | null
|
10
|
-
}
|
11
|
-
|
12
|
-
export interface Config {
|
13
|
-
name: string
|
14
|
-
isConfigured: boolean
|
15
|
-
values: ConfigValue[]
|
16
|
-
type: string
|
17
|
-
}
|
18
|
-
|
19
|
-
export interface Tag {
|
20
|
-
name: string
|
21
|
-
}
|
22
|
-
|
23
|
-
export interface Tags {
|
24
|
-
tags: string[]
|
25
|
-
}
|
26
|
-
|
27
|
-
export interface RuleSet {
|
28
|
-
ruleIds: string[]
|
29
|
-
}
|
30
|
-
|
31
|
-
export interface DnsRecord {
|
32
|
-
resource: string
|
33
|
-
value: string
|
34
|
-
}
|
35
|
-
|
36
|
-
export interface Contact {
|
37
|
-
name: string | null
|
38
|
-
organization: string | null
|
39
|
-
}
|
40
|
-
|
41
|
-
export interface Registrar {
|
42
|
-
name: string | null
|
43
|
-
organization: string | null
|
44
|
-
}
|
45
|
-
|
46
|
-
export interface WhoisRecord {
|
47
|
-
createdOn: Date | null
|
48
|
-
updatedOn: Date | null
|
49
|
-
expiresOn: Date | null
|
50
|
-
registrar: Registrar | null
|
51
|
-
contacts: Contact[]
|
52
|
-
}
|
53
|
-
|
54
|
-
export interface AutonomousSystem {
|
55
|
-
asn: number
|
56
|
-
}
|
57
|
-
|
58
|
-
export interface Geolocation {
|
59
|
-
country: string
|
60
|
-
countryCode: string
|
61
|
-
}
|
62
|
-
|
63
|
-
export interface ReverseDnsName {
|
64
|
-
name: string
|
65
|
-
}
|
66
|
-
|
67
|
-
export interface CPE {
|
68
|
-
cpe: string
|
69
|
-
}
|
70
|
-
|
71
|
-
export interface Port {
|
72
|
-
port: string
|
73
|
-
}
|
74
|
-
|
75
|
-
export interface Artifact {
|
76
|
-
id: string
|
77
|
-
data: string
|
78
|
-
dataType: string
|
79
|
-
source: string
|
80
|
-
metadata: unknown | null
|
81
|
-
createdAt: string
|
82
|
-
|
83
|
-
autonomousSystem: AutonomousSystem | null
|
84
|
-
whoisRecord: WhoisRecord | null
|
85
|
-
geolocation: Geolocation | null
|
86
|
-
|
87
|
-
dnsRecords: DnsRecord[] | null
|
88
|
-
reverseDnsNames: ReverseDnsName[] | null
|
89
|
-
cpes: CPE[] | null
|
90
|
-
ports: Port[] | null
|
91
|
-
}
|
92
|
-
|
93
|
-
export interface ArtifactWithTags extends Artifact {
|
94
|
-
tags: string[]
|
95
|
-
}
|
96
|
-
|
97
|
-
export interface Alert {
|
98
|
-
id: string
|
99
|
-
ruleId: string
|
100
|
-
createdAt: string
|
101
|
-
|
102
|
-
tags: Tag[]
|
103
|
-
artifacts: Artifact[]
|
104
|
-
}
|
105
|
-
|
106
|
-
export interface Alerts extends Pagination {
|
107
|
-
alerts: Alert[]
|
108
|
-
}
|
109
|
-
|
110
|
-
export interface PaginationParams {
|
111
|
-
page: number | undefined
|
112
|
-
}
|
113
|
-
|
114
|
-
export interface AlertSearchParams extends PaginationParams {
|
115
|
-
artifact: string | undefined
|
116
|
-
ruleId: string | undefined
|
117
|
-
tag: string | undefined
|
118
|
-
fromAt: string | undefined
|
119
|
-
toAt: string | undefined
|
120
|
-
}
|
121
|
-
|
122
|
-
export interface IPInfo {
|
123
|
-
ip: string
|
124
|
-
hostname: string | null
|
125
|
-
loc: string
|
126
|
-
countryCode: string
|
127
|
-
asn: string
|
128
|
-
}
|
129
|
-
|
130
|
-
export interface GCS {
|
131
|
-
lat: number
|
132
|
-
long: number
|
133
|
-
}
|
134
|
-
|
135
|
-
export interface Country {
|
136
|
-
name: string
|
137
|
-
code: string
|
138
|
-
lat: number
|
139
|
-
long: number
|
140
|
-
}
|
141
|
-
|
142
|
-
export type LinkType = "ip" | "domain" | "url" | "hash"
|
143
|
-
|
144
|
-
export interface Link {
|
145
|
-
name: string
|
146
|
-
type: string
|
147
|
-
baseURL: string
|
148
|
-
// eslint-disable-next-line no-unused-vars
|
149
|
-
href(data: string): string
|
150
|
-
favicon(): string
|
151
|
-
}
|
152
|
-
|
153
|
-
export interface Rule {
|
154
|
-
id: string
|
155
|
-
title: string
|
156
|
-
description: string
|
157
|
-
yaml: string
|
158
|
-
createdAt: string
|
159
|
-
updatedAt: string
|
160
|
-
tags: Tag[]
|
161
|
-
}
|
162
|
-
|
163
|
-
export interface CreateRule {
|
164
|
-
yaml: string
|
165
|
-
}
|
166
|
-
|
167
|
-
export interface UpdateRule {
|
168
|
-
id: string
|
169
|
-
yaml: string
|
170
|
-
}
|
171
|
-
|
172
|
-
export interface Query {
|
173
|
-
analyzer: string
|
174
|
-
query: string
|
175
|
-
interval: null
|
176
|
-
}
|
177
|
-
|
178
|
-
export interface Rules extends Pagination {
|
179
|
-
rules: Rule[]
|
180
|
-
}
|
181
|
-
|
182
|
-
export interface RuleSearchParams extends PaginationParams {
|
183
|
-
description: string | undefined
|
184
|
-
tag: string | undefined
|
185
|
-
title: string | undefined
|
186
|
-
fromAt: string | undefined
|
187
|
-
toAt: string | undefined
|
188
|
-
}
|
data/frontend/src/utils.ts
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
import dayjs from "dayjs"
|
2
|
-
import relativeTime from "dayjs/plugin/relativeTime"
|
3
|
-
import timezone from "dayjs/plugin/timezone"
|
4
|
-
import utc from "dayjs/plugin/utc"
|
5
|
-
import type { LocationQueryValue } from "vue-router"
|
6
|
-
|
7
|
-
import { getCountryByCode } from "@/countries"
|
8
|
-
import type { GCS, IPInfo } from "@/types"
|
9
|
-
|
10
|
-
dayjs.extend(relativeTime)
|
11
|
-
dayjs.extend(timezone)
|
12
|
-
dayjs.extend(utc)
|
13
|
-
|
14
|
-
export function getLocalDatetime(datetime: string): string {
|
15
|
-
return dayjs(datetime).local().format("YYYY-MM-DD HH:mm:ss")
|
16
|
-
}
|
17
|
-
|
18
|
-
export function getHumanizedRelativeTime(datetime: string): string {
|
19
|
-
return dayjs(datetime).local().fromNow()
|
20
|
-
}
|
21
|
-
|
22
|
-
export function getGCSByCountryCode(countryCode: string): GCS | undefined {
|
23
|
-
const country = getCountryByCode(countryCode)
|
24
|
-
if (country !== undefined) {
|
25
|
-
return { lat: country.lat, long: country.long }
|
26
|
-
}
|
27
|
-
}
|
28
|
-
|
29
|
-
export function getGCSByIPInfo(ipinfo: IPInfo): GCS | undefined {
|
30
|
-
if (ipinfo.loc !== undefined) {
|
31
|
-
const numbers = ipinfo.loc.split(",")
|
32
|
-
if (numbers.length === 2) {
|
33
|
-
const lat = numbers[0]
|
34
|
-
const long = numbers[1]
|
35
|
-
|
36
|
-
return { lat: parseFloat(lat), long: parseFloat(long) }
|
37
|
-
}
|
38
|
-
}
|
39
|
-
return getGCSByCountryCode(ipinfo.countryCode)
|
40
|
-
}
|
41
|
-
|
42
|
-
export function normalizeQueryParam(
|
43
|
-
param: undefined | null | string | string[] | LocationQueryValue | LocationQueryValue[]
|
44
|
-
): string | undefined {
|
45
|
-
if (param === undefined || param === null) {
|
46
|
-
return undefined
|
47
|
-
}
|
48
|
-
|
49
|
-
if (typeof param === "string") {
|
50
|
-
return param
|
51
|
-
}
|
52
|
-
|
53
|
-
return param.toString()
|
54
|
-
}
|
@@ -1,20 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Alerts></Alerts>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent } from "vue"
|
8
|
-
|
9
|
-
import Alerts from "@/components/alert/AlertsWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "AlertsView",
|
13
|
-
components: {
|
14
|
-
Alerts
|
15
|
-
},
|
16
|
-
setup() {
|
17
|
-
useTitle("Alerts - Mihari")
|
18
|
-
}
|
19
|
-
})
|
20
|
-
</script>
|
@@ -1,39 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Artifact :id="id"></Artifact>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent, onMounted, watch } from "vue"
|
8
|
-
|
9
|
-
import Artifact from "@/components/artifact/ArtifactWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "ArtifactView",
|
13
|
-
components: {
|
14
|
-
Artifact
|
15
|
-
},
|
16
|
-
props: {
|
17
|
-
id: {
|
18
|
-
type: String,
|
19
|
-
required: true
|
20
|
-
}
|
21
|
-
},
|
22
|
-
setup(props) {
|
23
|
-
const updateTitle = () => {
|
24
|
-
useTitle(`Artifact:${props.id} - Mihari`)
|
25
|
-
}
|
26
|
-
|
27
|
-
onMounted(() => {
|
28
|
-
updateTitle()
|
29
|
-
})
|
30
|
-
|
31
|
-
watch(
|
32
|
-
() => props.id,
|
33
|
-
() => {
|
34
|
-
updateTitle()
|
35
|
-
}
|
36
|
-
)
|
37
|
-
}
|
38
|
-
})
|
39
|
-
</script>
|
@@ -1,20 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Configs></Configs>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent } from "vue"
|
8
|
-
|
9
|
-
import Configs from "@/components/config/ConfigsWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "ConfigView",
|
13
|
-
components: {
|
14
|
-
Configs
|
15
|
-
},
|
16
|
-
setup() {
|
17
|
-
useTitle("Config - Mihari")
|
18
|
-
}
|
19
|
-
})
|
20
|
-
</script>
|
@@ -1,39 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<EditRule :id="id"></EditRule>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent, onMounted, watch } from "vue"
|
8
|
-
|
9
|
-
import EditRule from "@/components/rule/EditRuleWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "EditRuleView",
|
13
|
-
components: {
|
14
|
-
EditRule
|
15
|
-
},
|
16
|
-
props: {
|
17
|
-
id: {
|
18
|
-
type: String,
|
19
|
-
required: true
|
20
|
-
}
|
21
|
-
},
|
22
|
-
setup(props) {
|
23
|
-
const updateTitle = () => {
|
24
|
-
useTitle(`Edit rule:${props.id} - Mihari`)
|
25
|
-
}
|
26
|
-
|
27
|
-
onMounted(() => {
|
28
|
-
updateTitle()
|
29
|
-
})
|
30
|
-
|
31
|
-
watch(
|
32
|
-
() => props.id,
|
33
|
-
() => {
|
34
|
-
updateTitle()
|
35
|
-
}
|
36
|
-
)
|
37
|
-
}
|
38
|
-
})
|
39
|
-
</script>
|
@@ -1,26 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<NewRule></NewRule>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent, onMounted } from "vue"
|
8
|
-
|
9
|
-
import NewRule from "@/components/rule/NewRule.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "NewRuleView",
|
13
|
-
components: {
|
14
|
-
NewRule
|
15
|
-
},
|
16
|
-
setup() {
|
17
|
-
const updateTitle = () => {
|
18
|
-
useTitle(`New rule - Mihari`)
|
19
|
-
}
|
20
|
-
|
21
|
-
onMounted(() => {
|
22
|
-
updateTitle()
|
23
|
-
})
|
24
|
-
}
|
25
|
-
})
|
26
|
-
</script>
|
data/frontend/src/views/Rule.vue
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Rule :id="id"></Rule>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent, onMounted, watch } from "vue"
|
8
|
-
|
9
|
-
import Rule from "@/components/rule/RuleWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "RuleView",
|
13
|
-
components: {
|
14
|
-
Rule
|
15
|
-
},
|
16
|
-
props: {
|
17
|
-
id: {
|
18
|
-
type: String,
|
19
|
-
required: true
|
20
|
-
}
|
21
|
-
},
|
22
|
-
setup(props) {
|
23
|
-
const updateTitle = () => {
|
24
|
-
useTitle(`Rule:${props.id} - Mihari`)
|
25
|
-
}
|
26
|
-
|
27
|
-
onMounted(() => {
|
28
|
-
updateTitle()
|
29
|
-
})
|
30
|
-
|
31
|
-
watch(
|
32
|
-
() => props.id,
|
33
|
-
() => {
|
34
|
-
updateTitle()
|
35
|
-
}
|
36
|
-
)
|
37
|
-
}
|
38
|
-
})
|
39
|
-
</script>
|
@@ -1,20 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<Rules></Rules>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script lang="ts">
|
6
|
-
import { useTitle } from "@vueuse/core"
|
7
|
-
import { defineComponent } from "vue"
|
8
|
-
|
9
|
-
import Rules from "@/components/rule/RulesWrapper.vue"
|
10
|
-
|
11
|
-
export default defineComponent({
|
12
|
-
name: "RulesView",
|
13
|
-
components: {
|
14
|
-
Rules
|
15
|
-
},
|
16
|
-
setup() {
|
17
|
-
useTitle("Rules - Mihari")
|
18
|
-
}
|
19
|
-
})
|
20
|
-
</script>
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
2
|
-
|
3
|
-
import { getHumanizedRelativeTime } from '@/utils'
|
4
|
-
|
5
|
-
describe('getHumanizedRelativeTime', () => {
|
6
|
-
it('returns a relative time in humanized format', () => {
|
7
|
-
expect(getHumanizedRelativeTime('1970-01-01 00:00:00')).toContain('years')
|
8
|
-
})
|
9
|
-
})
|
data/frontend/tsconfig.app.json
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
3
|
-
"include": [
|
4
|
-
"env.d.ts",
|
5
|
-
"src/**/*",
|
6
|
-
"src/**/*.vue",
|
7
|
-
"tests/**/*"
|
8
|
-
],
|
9
|
-
"exclude": [
|
10
|
-
"src/**/__tests__/*"
|
11
|
-
],
|
12
|
-
"compilerOptions": {
|
13
|
-
"composite": true,
|
14
|
-
"baseUrl": ".",
|
15
|
-
"paths": {
|
16
|
-
"@/*": [
|
17
|
-
"./src/*"
|
18
|
-
]
|
19
|
-
}
|
20
|
-
}
|
21
|
-
}
|
data/frontend/tsconfig.json
DELETED
data/frontend/tsconfig.node.json
DELETED
data/frontend/vite.config.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import { fileURLToPath, URL } from "node:url"
|
2
|
-
|
3
|
-
import vue from "@vitejs/plugin-vue"
|
4
|
-
import { defineConfig } from "vite"
|
5
|
-
|
6
|
-
const env = process.env
|
7
|
-
const target = env.BACKEND_URL || "http://localhost:9292/"
|
8
|
-
const port = parseInt(env.port || "8080")
|
9
|
-
|
10
|
-
// https://vitejs.dev/config/
|
11
|
-
export default defineConfig({
|
12
|
-
plugins: [vue()],
|
13
|
-
server: {
|
14
|
-
port,
|
15
|
-
proxy: {
|
16
|
-
"/api": target
|
17
|
-
}
|
18
|
-
},
|
19
|
-
resolve: {
|
20
|
-
alias: {
|
21
|
-
"@": fileURLToPath(new URL("./src", import.meta.url))
|
22
|
-
}
|
23
|
-
}
|
24
|
-
})
|
data/frontend/vitest.config.ts
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
import { fileURLToPath } from "node:url"
|
2
|
-
|
3
|
-
import { mergeConfig } from "vite"
|
4
|
-
import { configDefaults, defineConfig } from "vitest/config"
|
5
|
-
|
6
|
-
import viteConfig from "./vite.config"
|
7
|
-
|
8
|
-
export default mergeConfig(
|
9
|
-
viteConfig,
|
10
|
-
defineConfig({
|
11
|
-
test: {
|
12
|
-
environment: "jsdom",
|
13
|
-
exclude: [...configDefaults.exclude, "e2e/*"],
|
14
|
-
root: fileURLToPath(new URL("./", import.meta.url)),
|
15
|
-
transformMode: {
|
16
|
-
web: [/\.[jt]sx$/]
|
17
|
-
},
|
18
|
-
include: ["**/__tests__/**/*.?(c|m)[jt]s?(x)", "**/?(*.){test,spec}.?(c|m)[jt]s?(x)"]
|
19
|
-
}
|
20
|
-
})
|
21
|
-
)
|
@@ -1,92 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module Mihari
|
6
|
-
module Services
|
7
|
-
class AlertProxy
|
8
|
-
# @return [Hash]
|
9
|
-
attr_reader :data
|
10
|
-
|
11
|
-
# @return [Array, nil]
|
12
|
-
attr_reader :errors
|
13
|
-
|
14
|
-
#
|
15
|
-
# Initialize
|
16
|
-
#
|
17
|
-
# @param [Hash] data
|
18
|
-
#
|
19
|
-
def initialize(**data)
|
20
|
-
@data = data.deep_symbolize_keys
|
21
|
-
@errors = nil
|
22
|
-
|
23
|
-
validate!
|
24
|
-
end
|
25
|
-
|
26
|
-
#
|
27
|
-
# @return [Boolean]
|
28
|
-
#
|
29
|
-
def errors?
|
30
|
-
return false if @errors.nil?
|
31
|
-
|
32
|
-
!@errors.empty?
|
33
|
-
end
|
34
|
-
|
35
|
-
def validate!
|
36
|
-
contract = Schemas::AlertContract.new
|
37
|
-
result = contract.call(data)
|
38
|
-
|
39
|
-
@data = result.to_h
|
40
|
-
@errors = result.errors
|
41
|
-
|
42
|
-
raise ValidationError.new("Validation failed", errors) if errors?
|
43
|
-
end
|
44
|
-
|
45
|
-
def [](key)
|
46
|
-
data key.to_sym
|
47
|
-
end
|
48
|
-
|
49
|
-
#
|
50
|
-
# @return [String]
|
51
|
-
#
|
52
|
-
def rule_id
|
53
|
-
@rule_id ||= data[:rule_id]
|
54
|
-
end
|
55
|
-
|
56
|
-
#
|
57
|
-
# @return [Array<Mihari::Models::Artifact>]
|
58
|
-
#
|
59
|
-
def artifacts
|
60
|
-
@artifacts ||= data[:artifacts].map do |data|
|
61
|
-
artifact = Models::Artifact.new(data: data)
|
62
|
-
artifact.rule_id = rule_id
|
63
|
-
artifact
|
64
|
-
end.uniq(&:data).select(&:valid?)
|
65
|
-
end
|
66
|
-
|
67
|
-
#
|
68
|
-
# @return [Mihari::Rule]
|
69
|
-
#
|
70
|
-
def rule
|
71
|
-
@rule ||= [].tap do |out|
|
72
|
-
data = Mihari::Models::Rule.find(rule_id).data
|
73
|
-
out << Rule.new(**data)
|
74
|
-
end.first
|
75
|
-
end
|
76
|
-
|
77
|
-
class << self
|
78
|
-
#
|
79
|
-
# Load rule from YAML string
|
80
|
-
#
|
81
|
-
# @param [String] yaml
|
82
|
-
#
|
83
|
-
# @return [Mihari::Services::Alert]
|
84
|
-
#
|
85
|
-
def from_yaml(yaml)
|
86
|
-
data = YAML.safe_load(yaml, permitted_classes: [Date, Symbol])
|
87
|
-
new(**data)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,8 +0,0 @@
|
|
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.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++n<f){o=e.getLine(n);var h=o.search(i);if(h==-1)continue;if(o[h]!="#")break;c=n}if(c>l){var p=e.getLine(c).length;return new s(l,a,c,p)}},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/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee","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/coffee").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
|
-
|