mihari 5.6.2 → 5.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/README.md +1 -0
  4. data/config.ru +1 -1
  5. data/lib/mihari/actor.rb +18 -2
  6. data/lib/mihari/analyzers/base.rb +13 -12
  7. data/lib/mihari/analyzers/binaryedge.rb +4 -1
  8. data/lib/mihari/analyzers/censys.rb +4 -2
  9. data/lib/mihari/analyzers/circl.rb +4 -1
  10. data/lib/mihari/analyzers/crtsh.rb +4 -1
  11. data/lib/mihari/analyzers/dnstwister.rb +4 -1
  12. data/lib/mihari/analyzers/feed.rb +3 -0
  13. data/lib/mihari/analyzers/fofa.rb +65 -0
  14. data/lib/mihari/analyzers/greynoise.rb +4 -1
  15. data/lib/mihari/analyzers/hunterhow.rb +6 -1
  16. data/lib/mihari/analyzers/onyphe.rb +4 -1
  17. data/lib/mihari/analyzers/otx.rb +4 -1
  18. data/lib/mihari/analyzers/passivetotal.rb +4 -1
  19. data/lib/mihari/analyzers/pulsedive.rb +3 -0
  20. data/lib/mihari/analyzers/securitytrails.rb +4 -1
  21. data/lib/mihari/analyzers/shodan.rb +4 -1
  22. data/lib/mihari/analyzers/urlscan.rb +4 -1
  23. data/lib/mihari/analyzers/virustotal.rb +4 -1
  24. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -1
  25. data/lib/mihari/analyzers/zoomeye.rb +5 -2
  26. data/lib/mihari/cli/alert.rb +3 -0
  27. data/lib/mihari/cli/base.rb +3 -0
  28. data/lib/mihari/cli/database.rb +3 -0
  29. data/lib/mihari/cli/main.rb +3 -0
  30. data/lib/mihari/cli/rule.rb +3 -0
  31. data/lib/mihari/clients/base.rb +3 -0
  32. data/lib/mihari/clients/binaryedge.rb +5 -2
  33. data/lib/mihari/clients/censys.rb +7 -4
  34. data/lib/mihari/clients/circl.rb +3 -0
  35. data/lib/mihari/clients/crtsh.rb +3 -0
  36. data/lib/mihari/clients/dnstwister.rb +3 -0
  37. data/lib/mihari/clients/fofa.rb +83 -0
  38. data/lib/mihari/clients/greynoise.rb +5 -2
  39. data/lib/mihari/clients/hunterhow.rb +5 -2
  40. data/lib/mihari/clients/misp.rb +3 -0
  41. data/lib/mihari/clients/onyphe.rb +5 -2
  42. data/lib/mihari/clients/otx.rb +3 -0
  43. data/lib/mihari/clients/passivetotal.rb +3 -0
  44. data/lib/mihari/clients/publsedive.rb +4 -1
  45. data/lib/mihari/clients/securitytrails.rb +3 -0
  46. data/lib/mihari/clients/shodan.rb +5 -2
  47. data/lib/mihari/clients/the_hive.rb +3 -0
  48. data/lib/mihari/clients/urlscan.rb +7 -4
  49. data/lib/mihari/clients/virustotal.rb +5 -2
  50. data/lib/mihari/clients/zoomeye.rb +3 -0
  51. data/lib/mihari/commands/alert.rb +9 -16
  52. data/lib/mihari/commands/database.rb +3 -0
  53. data/lib/mihari/commands/rule.rb +10 -1
  54. data/lib/mihari/commands/search.rb +13 -29
  55. data/lib/mihari/commands/version.rb +3 -0
  56. data/lib/mihari/commands/web.rb +4 -1
  57. data/lib/mihari/config.rb +139 -150
  58. data/lib/mihari/constants.rb +1 -1
  59. data/lib/mihari/database.rb +6 -0
  60. data/lib/mihari/emitters/base.rb +13 -11
  61. data/lib/mihari/emitters/database.rb +4 -1
  62. data/lib/mihari/emitters/misp.rb +7 -4
  63. data/lib/mihari/emitters/slack.rb +3 -3
  64. data/lib/mihari/emitters/the_hive.rb +3 -3
  65. data/lib/mihari/emitters/webhook.rb +4 -3
  66. data/lib/mihari/enrichers/base.rb +15 -9
  67. data/lib/mihari/enrichers/google_public_dns.rb +6 -5
  68. data/lib/mihari/enrichers/ipinfo.rb +11 -9
  69. data/lib/mihari/enrichers/shodan.rb +4 -6
  70. data/lib/mihari/enrichers/whois.rb +12 -9
  71. data/lib/mihari/entities/tag.rb +1 -0
  72. data/lib/mihari/errors.rb +6 -0
  73. data/lib/mihari/feed/parser.rb +3 -0
  74. data/lib/mihari/feed/reader.rb +3 -0
  75. data/lib/mihari/http.rb +6 -0
  76. data/lib/mihari/mixins/autonomous_system.rb +3 -0
  77. data/lib/mihari/mixins/configurable.rb +3 -0
  78. data/lib/mihari/mixins/error_notification.rb +3 -0
  79. data/lib/mihari/mixins/falsepositive.rb +3 -0
  80. data/lib/mihari/mixins/refang.rb +3 -0
  81. data/lib/mihari/mixins/retriable.rb +6 -2
  82. data/lib/mihari/models/alert.rb +7 -4
  83. data/lib/mihari/models/artifact.rb +6 -0
  84. data/lib/mihari/models/autonomous_system.rb +4 -1
  85. data/lib/mihari/models/cpe.rb +4 -1
  86. data/lib/mihari/models/dns.rb +4 -1
  87. data/lib/mihari/models/geolocation.rb +4 -1
  88. data/lib/mihari/models/port.rb +4 -1
  89. data/lib/mihari/models/reverse_dns.rb +4 -1
  90. data/lib/mihari/models/rule.rb +6 -3
  91. data/lib/mihari/models/tag.rb +3 -0
  92. data/lib/mihari/models/tagging.rb +3 -0
  93. data/lib/mihari/models/whois.rb +4 -3
  94. data/lib/mihari/rule.rb +31 -12
  95. data/lib/mihari/schemas/alert.rb +3 -0
  96. data/lib/mihari/schemas/analyzer.rb +11 -0
  97. data/lib/mihari/schemas/emitter.rb +3 -0
  98. data/lib/mihari/schemas/enricher.rb +3 -0
  99. data/lib/mihari/schemas/macros.rb +4 -0
  100. data/lib/mihari/schemas/mixins.rb +5 -0
  101. data/lib/mihari/schemas/rule.rb +3 -0
  102. data/lib/mihari/service.rb +26 -0
  103. data/lib/mihari/services/alert_builder.rb +85 -9
  104. data/lib/mihari/services/alert_runner.rb +8 -19
  105. data/lib/mihari/services/rule_builder.rb +13 -12
  106. data/lib/mihari/services/rule_runner.rb +7 -32
  107. data/lib/mihari/structs/binaryedge.rb +22 -28
  108. data/lib/mihari/structs/censys.rb +48 -141
  109. data/lib/mihari/structs/config.rb +19 -30
  110. data/lib/mihari/structs/filters.rb +38 -0
  111. data/lib/mihari/structs/fofa.rb +47 -0
  112. data/lib/mihari/structs/google_public_dns.rb +10 -32
  113. data/lib/mihari/structs/greynoise.rb +33 -90
  114. data/lib/mihari/structs/hunterhow.rb +24 -28
  115. data/lib/mihari/structs/ipinfo.rb +14 -37
  116. data/lib/mihari/structs/onyphe.rb +31 -80
  117. data/lib/mihari/structs/shodan.rb +47 -114
  118. data/lib/mihari/structs/urlscan.rb +24 -69
  119. data/lib/mihari/structs/virustotal_intelligence.rb +20 -64
  120. data/lib/mihari/type_checker.rb +4 -0
  121. data/lib/mihari/types.rb +3 -0
  122. data/lib/mihari/version.rb +1 -1
  123. data/lib/mihari/web/api.rb +15 -10
  124. data/lib/mihari/web/app.rb +64 -56
  125. data/lib/mihari/web/endpoints/alerts.rb +127 -85
  126. data/lib/mihari/web/endpoints/artifacts.rb +91 -79
  127. data/lib/mihari/web/endpoints/configs.rb +18 -13
  128. data/lib/mihari/web/endpoints/ip_addresses.rb +35 -15
  129. data/lib/mihari/web/endpoints/rules.rb +236 -187
  130. data/lib/mihari/web/endpoints/tags.rb +42 -35
  131. data/lib/mihari/web/middleware/connection_adapter.rb +16 -9
  132. data/lib/mihari/web/middleware/error_notification_adapter.rb +17 -10
  133. data/lib/mihari/web/public/assets/{index-28d4c79d.js → index-07fafab5.js} +31 -30
  134. data/lib/mihari/web/public/assets/mode-yaml-24faa242.js +8 -0
  135. data/lib/mihari/web/public/index.html +1 -1
  136. data/lib/mihari.rb +24 -6
  137. data/mihari.gemspec +9 -2
  138. data/mkdocs.yml +4 -2
  139. metadata +38 -133
  140. data/docs/alternatives.md +0 -5
  141. data/docs/analyzers/binaryedge.md +0 -26
  142. data/docs/analyzers/censys.md +0 -31
  143. data/docs/analyzers/circl.md +0 -37
  144. data/docs/analyzers/crtsh.md +0 -26
  145. data/docs/analyzers/dnstwister.md +0 -25
  146. data/docs/analyzers/feed.md +0 -73
  147. data/docs/analyzers/greynoise.md +0 -26
  148. data/docs/analyzers/hunterhow.md +0 -33
  149. data/docs/analyzers/index.md +0 -103
  150. data/docs/analyzers/onyphe.md +0 -26
  151. data/docs/analyzers/otx.md +0 -28
  152. data/docs/analyzers/passivetotal.md +0 -52
  153. data/docs/analyzers/pulsedive.md +0 -28
  154. data/docs/analyzers/securitytrails.md +0 -41
  155. data/docs/analyzers/shodan.md +0 -26
  156. data/docs/analyzers/urlscan.md +0 -28
  157. data/docs/analyzers/virustotal.md +0 -43
  158. data/docs/analyzers/virustotal_intelligence.md +0 -33
  159. data/docs/analyzers/zoomeye.md +0 -38
  160. data/docs/configuration.md +0 -35
  161. data/docs/emitters/database.md +0 -22
  162. data/docs/emitters/hive.md +0 -26
  163. data/docs/emitters/index.md +0 -36
  164. data/docs/emitters/misp.md +0 -21
  165. data/docs/emitters/slack.md +0 -21
  166. data/docs/emitters/webhook.md +0 -63
  167. data/docs/enrichers/google_public_dns.md +0 -19
  168. data/docs/enrichers/index.md +0 -35
  169. data/docs/enrichers/ipinfo.md +0 -26
  170. data/docs/enrichers/shodan.md +0 -22
  171. data/docs/enrichers/whois.md +0 -17
  172. data/docs/github_actions.md +0 -43
  173. data/docs/index.md +0 -11
  174. data/docs/installation.md +0 -31
  175. data/docs/requirements.md +0 -13
  176. data/docs/rule.md +0 -168
  177. data/docs/tags.md +0 -3
  178. data/docs/usage.md +0 -103
  179. data/frontend/.eslintrc.cjs +0 -22
  180. data/frontend/.gitignore +0 -31
  181. data/frontend/.prettierrc.json +0 -8
  182. data/frontend/README.md +0 -3
  183. data/frontend/env.d.ts +0 -5
  184. data/frontend/index.html +0 -21
  185. data/frontend/package-lock.json +0 -7219
  186. data/frontend/package.json +0 -67
  187. data/frontend/public/favicon.ico +0 -0
  188. data/frontend/scripts/swagger_doc_to_yaml.rb +0 -23
  189. data/frontend/src/App.vue +0 -27
  190. data/frontend/src/ace-config.ts +0 -6
  191. data/frontend/src/api-helper.ts +0 -111
  192. data/frontend/src/api.ts +0 -105
  193. data/frontend/src/components/ErrorMessage.vue +0 -31
  194. data/frontend/src/components/Loading.vue +0 -15
  195. data/frontend/src/components/Navbar.vue +0 -42
  196. data/frontend/src/components/Pagination.vue +0 -119
  197. data/frontend/src/components/alert/Alert.vue +0 -87
  198. data/frontend/src/components/alert/Alerts.vue +0 -63
  199. data/frontend/src/components/alert/AlertsWithPagination.vue +0 -90
  200. data/frontend/src/components/alert/AlertsWrapper.vue +0 -128
  201. data/frontend/src/components/alert/Form.vue +0 -182
  202. data/frontend/src/components/artifact/AS.vue +0 -29
  203. data/frontend/src/components/artifact/Artifact.vue +0 -287
  204. data/frontend/src/components/artifact/ArtifactTag.vue +0 -64
  205. data/frontend/src/components/artifact/ArtifactTags.vue +0 -29
  206. data/frontend/src/components/artifact/ArtifactWrapper.vue +0 -57
  207. data/frontend/src/components/artifact/CPEs.vue +0 -23
  208. data/frontend/src/components/artifact/DnsRecords.vue +0 -38
  209. data/frontend/src/components/artifact/Ports.vue +0 -23
  210. data/frontend/src/components/artifact/ReverseDnsNames.vue +0 -31
  211. data/frontend/src/components/artifact/Tags.vue +0 -29
  212. data/frontend/src/components/artifact/WhoisRecord.vue +0 -44
  213. data/frontend/src/components/config/Configs.vue +0 -65
  214. data/frontend/src/components/config/ConfigsWrapper.vue +0 -32
  215. data/frontend/src/components/link/Link.vue +0 -32
  216. data/frontend/src/components/link/Links.vue +0 -42
  217. data/frontend/src/components/rule/EditRule.vue +0 -72
  218. data/frontend/src/components/rule/EditRuleWrapper.vue +0 -48
  219. data/frontend/src/components/rule/Form.vue +0 -158
  220. data/frontend/src/components/rule/InputForm.vue +0 -45
  221. data/frontend/src/components/rule/NewRule.vue +0 -57
  222. data/frontend/src/components/rule/Rule.vue +0 -100
  223. data/frontend/src/components/rule/RuleWrapper.vue +0 -53
  224. data/frontend/src/components/rule/Rules.vue +0 -84
  225. data/frontend/src/components/rule/RulesWrapper.vue +0 -121
  226. data/frontend/src/components/rule/YAML.vue +0 -37
  227. data/frontend/src/components/tag/Tag.vue +0 -65
  228. data/frontend/src/components/tag/Tags.vue +0 -37
  229. data/frontend/src/countries.ts +0 -350
  230. data/frontend/src/index.ts +0 -20
  231. data/frontend/src/links/anyrun.ts +0 -19
  232. data/frontend/src/links/base.ts +0 -14
  233. data/frontend/src/links/censys.ts +0 -20
  234. data/frontend/src/links/crtsh.ts +0 -20
  235. data/frontend/src/links/dnslytics.ts +0 -38
  236. data/frontend/src/links/greynoise.ts +0 -20
  237. data/frontend/src/links/index.ts +0 -40
  238. data/frontend/src/links/intezer.ts +0 -20
  239. data/frontend/src/links/otx.ts +0 -33
  240. data/frontend/src/links/securitytrails.ts +0 -38
  241. data/frontend/src/links/shodan.ts +0 -20
  242. data/frontend/src/links/urlscan.ts +0 -50
  243. data/frontend/src/links/virustotal.ts +0 -72
  244. data/frontend/src/main.ts +0 -41
  245. data/frontend/src/router/index.ts +0 -57
  246. data/frontend/src/rule.ts +0 -14
  247. data/frontend/src/shims-vue.d.ts +0 -6
  248. data/frontend/src/swagger.yaml +0 -771
  249. data/frontend/src/types.ts +0 -188
  250. data/frontend/src/utils.ts +0 -54
  251. data/frontend/src/views/Alerts.vue +0 -20
  252. data/frontend/src/views/Artifact.vue +0 -39
  253. data/frontend/src/views/Configs.vue +0 -20
  254. data/frontend/src/views/EditRule.vue +0 -39
  255. data/frontend/src/views/NewRule.vue +0 -26
  256. data/frontend/src/views/Rule.vue +0 -39
  257. data/frontend/src/views/Rules.vue +0 -20
  258. data/frontend/tests/utils.spec.ts +0 -9
  259. data/frontend/tsconfig.app.json +0 -21
  260. data/frontend/tsconfig.json +0 -14
  261. data/frontend/tsconfig.node.json +0 -13
  262. data/frontend/tsconfig.vitest.json +0 -12
  263. data/frontend/vite.config.ts +0 -24
  264. data/frontend/vitest.config.ts +0 -21
  265. data/lib/mihari/services/alert_proxy.rb +0 -92
  266. data/lib/mihari/templates/rule.yml.erb +0 -5
  267. data/lib/mihari/web/public/assets/mode-yaml-a21faa53.js +0 -8
@@ -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
- }
@@ -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>
@@ -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
- })
@@ -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
- }
@@ -1,14 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- {
5
- "path": "./tsconfig.node.json"
6
- },
7
- {
8
- "path": "./tsconfig.app.json"
9
- },
10
- {
11
- "path": "./tsconfig.vitest.json"
12
- }
13
- ]
14
- }
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "@tsconfig/node20/tsconfig.json",
3
- "include": [
4
- "vite.config.*",
5
- ],
6
- "compilerOptions": {
7
- "composite": true,
8
- "module": "ESNext",
9
- "types": [
10
- "node"
11
- ]
12
- }
13
- }
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.app.json",
3
- "exclude": [],
4
- "compilerOptions": {
5
- "composite": true,
6
- "lib": [],
7
- "types": [
8
- "node",
9
- "jsdom"
10
- ]
11
- }
12
- }
@@ -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
- })
@@ -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,5 +0,0 @@
1
- id: <%= SecureRandom.uuid %>
2
- title: Title goes here
3
- description: Description goes here
4
- created_on: <%= Date.today %>
5
- queries: []
@@ -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
-