ronin-db-activerecord 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/COPYING.txt +165 -0
  9. data/ChangeLog.md +39 -0
  10. data/Gemfile +27 -0
  11. data/README.md +143 -0
  12. data/Rakefile +72 -0
  13. data/db/migrate/0001_create_ronin_ip_address_mac_addresses_table.rb +43 -0
  14. data/db/migrate/0002_create_ronin_vulnerabilities_table.rb +61 -0
  15. data/db/migrate/0003_create_ronin_url_schemes_table.rb +32 -0
  16. data/db/migrate/0004_create_ronin_url_query_param_names_table.rb +32 -0
  17. data/db/migrate/0005_create_ronin_user_names_table.rb +33 -0
  18. data/db/migrate/0006_create_ronin_software_vendors_table.rb +32 -0
  19. data/db/migrate/0007_create_ronin_advisories_table.rb +42 -0
  20. data/db/migrate/0008_create_ronin_host_name_ip_addresses_table.rb +43 -0
  21. data/db/migrate/0009_create_ronin_host_names_table.rb +34 -0
  22. data/db/migrate/0010_create_ronin_arches_table.rb +37 -0
  23. data/db/migrate/0011_create_ronin_email_addresses_table.rb +44 -0
  24. data/db/migrate/0012_create_ronin_oses_table.rb +36 -0
  25. data/db/migrate/0013_create_ronin_organizations_table.rb +31 -0
  26. data/db/migrate/0014_create_ronin_ip_addresses_table.rb +35 -0
  27. data/db/migrate/0015_create_ronin_os_guesses_table.rb +40 -0
  28. data/db/migrate/0016_create_ronin_url_query_params_table.rb +42 -0
  29. data/db/migrate/0017_create_ronin_passwords_table.rb +32 -0
  30. data/db/migrate/0018_create_ronin_open_ports_table.rb +46 -0
  31. data/db/migrate/0019_create_ronin_urls_table.rb +50 -0
  32. data/db/migrate/0020_create_ronin_softwares_table.rb +39 -0
  33. data/db/migrate/0021_create_ronin_mac_addresses_table.rb +33 -0
  34. data/db/migrate/0022_create_ronin_countries_table.rb +34 -0
  35. data/db/migrate/0023_create_ronin_services_table.rb +32 -0
  36. data/db/migrate/0024_create_ronin_credentials_table.rb +44 -0
  37. data/db/migrate/0025_create_ronin_ports_table.rb +33 -0
  38. data/db/migrate/0026_create_ronin_asns_table.rb +44 -0
  39. data/db/migrate/0027_create_ronin_http_query_param_names_table.rb +32 -0
  40. data/db/migrate/0028_create_ronin_http_query_params_table.rb +42 -0
  41. data/db/migrate/0029_create_ronin_http_header_names_table.rb +31 -0
  42. data/db/migrate/0030_create_ronin_http_request_headers_table.rb +41 -0
  43. data/db/migrate/0031_create_ronin_http_response_headers_table.rb +41 -0
  44. data/db/migrate/0032_create_ronin_http_requests_table.rb +41 -0
  45. data/db/migrate/0033_create_ronin_http_responses_table.rb +36 -0
  46. data/db/migrate/0034_create_ronin_service_credentials_table.rb +41 -0
  47. data/db/migrate/0035_create_ronin_web_credentials_table.rb +41 -0
  48. data/gemspec.yml +28 -0
  49. data/lib/ronin/db/address.rb +105 -0
  50. data/lib/ronin/db/advisory.rb +169 -0
  51. data/lib/ronin/db/arch.rb +160 -0
  52. data/lib/ronin/db/asn.rb +212 -0
  53. data/lib/ronin/db/credential.rb +248 -0
  54. data/lib/ronin/db/email_address.rb +225 -0
  55. data/lib/ronin/db/host_name.rb +224 -0
  56. data/lib/ronin/db/host_name_ip_address.rb +65 -0
  57. data/lib/ronin/db/http_header_name.rb +75 -0
  58. data/lib/ronin/db/http_query_param.rb +79 -0
  59. data/lib/ronin/db/http_query_param_name.rb +76 -0
  60. data/lib/ronin/db/http_request.rb +120 -0
  61. data/lib/ronin/db/http_request_header.rb +78 -0
  62. data/lib/ronin/db/http_response.rb +91 -0
  63. data/lib/ronin/db/http_response_header.rb +78 -0
  64. data/lib/ronin/db/ip_address.rb +351 -0
  65. data/lib/ronin/db/ip_address_mac_address.rb +62 -0
  66. data/lib/ronin/db/mac_address.rb +91 -0
  67. data/lib/ronin/db/migrations.rb +137 -0
  68. data/lib/ronin/db/model/has_name.rb +102 -0
  69. data/lib/ronin/db/model/has_unique_name.rb +82 -0
  70. data/lib/ronin/db/model/importable.rb +85 -0
  71. data/lib/ronin/db/model/last_scanned_at.rb +48 -0
  72. data/lib/ronin/db/model.rb +37 -0
  73. data/lib/ronin/db/models.rb +108 -0
  74. data/lib/ronin/db/open_port.rb +148 -0
  75. data/lib/ronin/db/organization.rb +50 -0
  76. data/lib/ronin/db/os.rb +183 -0
  77. data/lib/ronin/db/os_guess.rb +67 -0
  78. data/lib/ronin/db/password.rb +167 -0
  79. data/lib/ronin/db/port.rb +123 -0
  80. data/lib/ronin/db/root.rb +28 -0
  81. data/lib/ronin/db/schema_migration.rb +34 -0
  82. data/lib/ronin/db/service.rb +48 -0
  83. data/lib/ronin/db/service_credential.rb +66 -0
  84. data/lib/ronin/db/software.rb +85 -0
  85. data/lib/ronin/db/software_vendor.rb +42 -0
  86. data/lib/ronin/db/url.rb +497 -0
  87. data/lib/ronin/db/url_query_param.rb +79 -0
  88. data/lib/ronin/db/url_query_param_name.rb +76 -0
  89. data/lib/ronin/db/url_scheme.rb +80 -0
  90. data/lib/ronin/db/user_name.rb +96 -0
  91. data/lib/ronin/db/vulnerability.rb +81 -0
  92. data/lib/ronin/db/web_credential.rb +69 -0
  93. data/ronin-db-activerecord.gemspec +61 -0
  94. data/spec/advisory_spec.rb +277 -0
  95. data/spec/arch_spec.rb +228 -0
  96. data/spec/asn_spec.rb +504 -0
  97. data/spec/credential_spec.rb +362 -0
  98. data/spec/email_address_spec.rb +372 -0
  99. data/spec/host_name_ip_address_spec.rb +8 -0
  100. data/spec/host_name_spec.rb +207 -0
  101. data/spec/http_header_name_spec.rb +25 -0
  102. data/spec/http_query_param_name_spec.rb +25 -0
  103. data/spec/http_query_param_spec.rb +104 -0
  104. data/spec/http_request_header_spec.rb +72 -0
  105. data/spec/http_request_spec.rb +168 -0
  106. data/spec/http_response_header_spec.rb +74 -0
  107. data/spec/http_response_spec.rb +103 -0
  108. data/spec/ip_address_mac_addresses_spec.rb +8 -0
  109. data/spec/ip_address_spec.rb +386 -0
  110. data/spec/mac_address_spec.rb +67 -0
  111. data/spec/migrations_spec.rb +122 -0
  112. data/spec/model/has_name_spec.rb +65 -0
  113. data/spec/model/has_unique_name_spec.rb +61 -0
  114. data/spec/model/importable_spec.rb +105 -0
  115. data/spec/models_spec.rb +60 -0
  116. data/spec/open_port_spec.rb +87 -0
  117. data/spec/organization_spec.rb +10 -0
  118. data/spec/os_guess_spec.rb +43 -0
  119. data/spec/os_spec.rb +114 -0
  120. data/spec/password_spec.rb +81 -0
  121. data/spec/port_spec.rb +102 -0
  122. data/spec/schema_migration_spec.rb +8 -0
  123. data/spec/service_credential_spec.rb +43 -0
  124. data/spec/service_spec.rb +39 -0
  125. data/spec/software_spec.rb +76 -0
  126. data/spec/software_vendor_spec.rb +33 -0
  127. data/spec/spec_helper.rb +13 -0
  128. data/spec/url_query_param_name_spec.rb +25 -0
  129. data/spec/url_query_param_spec.rb +110 -0
  130. data/spec/url_scheme_spec.rb +39 -0
  131. data/spec/url_spec.rb +951 -0
  132. data/spec/user_name_spec.rb +54 -0
  133. data/spec/vulnerability_spec.rb +8 -0
  134. data/spec/web_credential_spec.rb +72 -0
  135. metadata +266 -0
@@ -0,0 +1,351 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/address'
22
+
23
+ require 'active_record'
24
+ require 'ipaddr'
25
+ require 'resolv'
26
+
27
+ module Ronin
28
+ module DB
29
+ #
30
+ # Represents IP addresses and their associated {HostName host names}
31
+ # and {MACAddress MAC addresses}.
32
+ #
33
+ class IPAddress < Address
34
+
35
+ # @!attribute [rw] address
36
+ # The IP Address.
37
+ #
38
+ # @return [String]
39
+ attribute :address, :string
40
+ validates :address, presence: true,
41
+ uniqueness: true,
42
+ length: {maximum: 39},
43
+ format: {
44
+ with: /#{Resolv::IPv4::Regex}|#{Resolv::IPv6::Regex}/,
45
+ message: 'Must be a valid IP address'
46
+ }
47
+
48
+ # @!attribute [rw] hton
49
+ # The IP address, but in network byte-order.
50
+ #
51
+ # @return [String]
52
+ attribute :hton, :binary
53
+ before_save :set_hton
54
+
55
+ # @!attribute [rw] version
56
+ # Type of the address.
57
+ #
58
+ # @return [Integer]
59
+ attribute :version, :integer
60
+ validates :version, inclusion: {in: [4, 6]}
61
+
62
+ # @!attribute [rw] ip_address_mac_addresses
63
+ # The MAC Addresses associations.
64
+ #
65
+ # @return [Array<IPAddressMACAddress>]
66
+ has_many :ip_address_mac_addresses, dependent: :destroy,
67
+ class_name: 'IPAddressMACAddress'
68
+
69
+ # @!attribute [rw] mac_addresses
70
+ # The MAC Addresses associated with the IP Address.
71
+ #
72
+ # @return [Array<MACAddress>]
73
+ has_many :mac_addresses, through: :ip_address_mac_addresses,
74
+ class_name: 'MACAddress'
75
+
76
+ # @!attribute [rw] host_name_ip_addresses
77
+ # The host-names that the IP Address serves.
78
+ #
79
+ # @return [Array<HostNameIPAddress>]
80
+ has_many :host_name_ip_addresses, dependent: :destroy,
81
+ class_name: 'HostNameIPAddress'
82
+
83
+ # @!attribute [rw] host_names
84
+ # The host-names associated with the IP Address.
85
+ #
86
+ # @return [Array<HostName>]
87
+ has_many :host_names, through: :host_name_ip_addresses
88
+
89
+ # @!attribute [rw] open_ports
90
+ # The open ports of the host.
91
+ #
92
+ # @return [Array<OpenPort>]
93
+ has_many :open_ports, dependent: :destroy
94
+
95
+ # @!attribute [rw] ports
96
+ # The ports of the host.
97
+ #
98
+ # @return [Array<Port>]
99
+ has_many :ports, through: :open_ports
100
+
101
+ # @!attribute [rw] os_guesses
102
+ # Any OS guesses against the IP Address.
103
+ #
104
+ # @return [Array<OSGuess>]
105
+ has_many :os_guesses, dependent: :destroy,
106
+ class_name: 'OSGuess'
107
+
108
+ # @!attribute [rw] oses
109
+ # Any OSes that the IP Address might be running
110
+ #
111
+ # @return [Array<OS>]
112
+ has_many :oses, through: :os_guesses,
113
+ class_name: 'OS'
114
+
115
+ #
116
+ # Searches for all IPv4 addresses.
117
+ #
118
+ # @return [Array<IPAddress>]
119
+ # The IPv4 addresses.
120
+ #
121
+ # @api public
122
+ #
123
+ def self.v4
124
+ where(version: 4)
125
+ end
126
+
127
+ #
128
+ # Searches for all IPv6 addresses.
129
+ #
130
+ # @return [Array<IPAddress>]
131
+ # The IPv6 addresses.
132
+ #
133
+ # @api public
134
+ #
135
+ def self.v6
136
+ where(version: 6)
137
+ end
138
+
139
+ #
140
+ # Queries all IP address that are between the first IP address and last IP
141
+ # address.
142
+ #
143
+ # @param [String] first_ip
144
+ # The first IP of the IP range.
145
+ #
146
+ # @param [String] last_ip
147
+ # The last IP of the IP range.
148
+ #
149
+ # @return [Array<IPAddress>]
150
+ #
151
+ def self.between(first_ip,last_ip)
152
+ first_ip_hton = IPAddr.new(first_ip).hton
153
+ last_ip_hton = IPAddr.new(last_ip).hton
154
+
155
+ hton = arel_table[:hton]
156
+
157
+ where(hton.gteq(first_ip_hton).and(hton.lteq(last_ip_hton)))
158
+ end
159
+
160
+ #
161
+ # Queries all IP addresses that exist in the range of IP addresses.
162
+ #
163
+ # @param [Range, #begin, #end] range
164
+ # The IP range to query.
165
+ #
166
+ # @return [Array<IPAddress>]
167
+ #
168
+ def self.in_range(range)
169
+ between(range.begin,range.end)
170
+ end
171
+
172
+ #
173
+ # Searches for all IP addresses associated with specific MAC address(es).
174
+ #
175
+ # @param [Array<String>, String] mac
176
+ # The MAC address(es) to search for.
177
+ #
178
+ # @return [Array<IPAddress>]
179
+ # The matching IP addresses.
180
+ #
181
+ # @api public
182
+ #
183
+ def self.with_mac_address(mac)
184
+ joins(:mac_addresses).where(mac_addresses: {address: mac})
185
+ end
186
+
187
+ #
188
+ # Searches for IP addresses associated with the given host name(s).
189
+ #
190
+ # @param [Array<String>, String] name
191
+ # The host name(s) to search for.
192
+ #
193
+ # @return [Array<IPAddress>]
194
+ # The matching IP addresses.
195
+ #
196
+ # @api public
197
+ #
198
+ def self.with_host_name(name)
199
+ joins(:host_names).where(host_names: {name: name})
200
+ end
201
+
202
+ #
203
+ # Searches for IP addresses with the given open port(s).
204
+ #
205
+ # @param [Array<Integer>, Integer] number
206
+ # The port number(s) to search for.
207
+ #
208
+ # @return [Array<IPAddress>]
209
+ # The matching IP addresses.
210
+ #
211
+ # @api public
212
+ #
213
+ def self.with_port_number(number)
214
+ joins(:ports).where(ports: {number: number})
215
+ end
216
+
217
+ #
218
+ # Initializes the IP address record.
219
+ #
220
+ # @param [Array] arguments
221
+ # Additional attribute arguments.
222
+ #
223
+ # @param [Hash{Symbol => Object}] kwargs
224
+ # Additional attribute values.
225
+ #
226
+ # @note Also assigns a default value to `version` based on the `address`.
227
+ #
228
+ def initialize(*arguments,**kwargs)
229
+ super(*arguments,**kwargs)
230
+
231
+ self.version ||= if ipaddr
232
+ if ipaddr.ipv6? then 6
233
+ else 4
234
+ end
235
+ end
236
+ end
237
+
238
+ #
239
+ # Sets the IP address'es address.
240
+ #
241
+ # @param [String, IPAddr, nil] new_address
242
+ # The new address to use.
243
+ #
244
+ # @return [String, IPAddr, nil]
245
+ # The IP address'es new address.
246
+ #
247
+ def address=(new_address)
248
+ @ipaddr = nil
249
+ super(new_address)
250
+ end
251
+
252
+ #
253
+ # Returns an `IPAddr` object for the IP address.
254
+ #
255
+ # @return [IPAddr]
256
+ # The IPAddr object representing either the IPv4 or IPv6 address.
257
+ #
258
+ # @api public
259
+ #
260
+ def ipaddr
261
+ @ipaddr ||= if self.address
262
+ begin
263
+ IPAddr.new(self.address)
264
+ rescue IPAddr::InvalidAddressError
265
+ end
266
+ end
267
+ end
268
+
269
+ #
270
+ # Queries the {ASN} record for the IP address.
271
+ #
272
+ # @return [ASN, nil]
273
+ #
274
+ def asn
275
+ ASN.containing_ip(ipaddr)
276
+ end
277
+
278
+ #
279
+ # The MAC Address that was most recently used by the IP Address.
280
+ #
281
+ # @return [MACAddress]
282
+ # The MAC Address that most recently used the IP Address.
283
+ #
284
+ # @api public
285
+ #
286
+ def recent_mac_address
287
+ self.ip_address_mac_addresses.order('created_at DESC').mac_addresses.first
288
+ end
289
+
290
+ #
291
+ # The host-name that was most recently used by the IP Address.
292
+ #
293
+ # @return [HostName]
294
+ # The host-name that most recently used by the IP Address.
295
+ #
296
+ # @api public
297
+ #
298
+ def recent_host_name
299
+ self.host_name_ip_addresses.order('created_at DESC').host_names.first
300
+ end
301
+
302
+ #
303
+ # The Operating System that was most recently guessed for the IP
304
+ # Address.
305
+ #
306
+ # @return [OS]
307
+ # The Operating System that most recently was guessed.
308
+ #
309
+ # @api public
310
+ #
311
+ def recent_os_guess
312
+ self.os_guesses.order('created_at DESC').oses.first
313
+ end
314
+
315
+ alias to_ip ipaddr
316
+
317
+ #
318
+ # Converts the address to an Integer.
319
+ #
320
+ # @return [Integer]
321
+ # The network representation of the IP address.
322
+ #
323
+ # @api public
324
+ #
325
+ def to_i
326
+ ipaddr.to_i
327
+ end
328
+
329
+ private
330
+
331
+ #
332
+ # Sets the `hton` attribute.
333
+ #
334
+ def set_hton
335
+ self.hton = self.ipaddr.hton
336
+ end
337
+
338
+ end
339
+ end
340
+ end
341
+
342
+ require 'ronin/db/ip_address_mac_address'
343
+ require 'ronin/db/mac_address'
344
+ require 'ronin/db/host_name_ip_address'
345
+ require 'ronin/db/host_name'
346
+ require 'ronin/db/open_port'
347
+ require 'ronin/db/port'
348
+ require 'ronin/db/host_name'
349
+ require 'ronin/db/os_guess'
350
+ require 'ronin/db/os'
351
+ require 'ronin/db/asn'
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/model'
22
+
23
+ require 'active_record'
24
+
25
+ module Ronin
26
+ module DB
27
+ #
28
+ # Associates an {IPAddress} with a {MACAddress}.
29
+ #
30
+ class IPAddressMACAddress < ActiveRecord::Base
31
+
32
+ include Model
33
+
34
+ # @!attribute [rw] id
35
+ # The primary-key of the join model.
36
+ #
37
+ # @return [Integer]
38
+ attribute :id, :integer
39
+
40
+ # @!attribute [rw] ip_address
41
+ # The IP Address.
42
+ #
43
+ # @return [IPAddress]
44
+ belongs_to :ip_address, required: true,
45
+ class_name: 'IPAddress'
46
+
47
+ # @!attribute [rw] mac_address
48
+ # The Mac Address.
49
+ #
50
+ # @return [MACAddress]
51
+ belongs_to :mac_address, required: true,
52
+ class_name: 'MACAddress'
53
+
54
+ # @!attribute [r] created_at
55
+ # Tracks when an IP Address becomes associated with a MAC Address.
56
+ #
57
+ # @return [Time]
58
+ attribute :created_at, :time
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/address'
22
+
23
+ require 'active_record'
24
+ require 'strscan'
25
+
26
+ module Ronin
27
+ module DB
28
+ #
29
+ # Represents MAC addresses and their associated {IPAddress IP addresses}.
30
+ #
31
+ class MACAddress < Address
32
+
33
+ # @!attribute [rw] address
34
+ # The MAC address.
35
+ #
36
+ # @return [String]
37
+ attribute :address, :string # length: 17..17,
38
+ validates :address, presence: true,
39
+ uniqueness: true,
40
+ length: {maximum: 17},
41
+ format: {
42
+ with: /[0-9a-fA-F]{2}(?::[0-9a-fA-F]{2}){5}/,
43
+ message: 'Must be a valid MAC address'
44
+ }
45
+
46
+ # @!attribute [rw] ip_address_mac_addresses
47
+ # The IP Addresses the MAC Address hosts
48
+ #
49
+ # @return [Array<IPAddressMACAddress>]
50
+ has_many :ip_address_mac_addresses, dependent: :destroy,
51
+ class_name: 'IPAddressMACAddress'
52
+
53
+ # @!attribute [rw] ip_addresses
54
+ # The IP Addresses associated with the MAC Address
55
+ #
56
+ # @return [Array<IPAddress>]
57
+ has_many :ip_addresses, through: :ip_address_mac_addresses,
58
+ class_name: 'IPAddress'
59
+
60
+ #
61
+ # The IP Address that most recently used the MAC Address.
62
+ #
63
+ # @return [IPAddress]
64
+ # The IP Address that most recently used the MAC Address.
65
+ #
66
+ # @api public
67
+ #
68
+ def recent_ip_address
69
+ self.ip_address_mac_addresses.order('created_at DESC').ip_addresses.first
70
+ end
71
+
72
+ #
73
+ # Converts the MAC address to an Integer.
74
+ #
75
+ # @return [Integer]
76
+ # The network representation of the MAC address.
77
+ #
78
+ # @api public
79
+ #
80
+ def to_i
81
+ self.address.split(':').inject(0) do |bits,char|
82
+ bits = ((bits << 8) | char.hex)
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+
90
+ require 'ronin/db/ip_address_mac_address'
91
+ require 'ronin/db/ip_address'
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
4
+ #
5
+ # Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-db-activerecord is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-db-activerecord is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/db/schema_migration'
22
+
23
+ require 'active_record'
24
+ require 'active_record/migration'
25
+
26
+ module Ronin
27
+ module DB
28
+ module Migrations
29
+ #
30
+ # The current migration version of the database.
31
+ #
32
+ # @return [Integer]
33
+ #
34
+ def self.current_version
35
+ context.current_version
36
+ end
37
+
38
+ #
39
+ # Determines if the database needs migrating up.
40
+ #
41
+ # @return [Boolean]
42
+ #
43
+ def self.needs_migration?
44
+ context.needs_migration?
45
+ end
46
+
47
+ #
48
+ # Migrates the database to the target version.
49
+ #
50
+ # @param [Integer, nil] target_version
51
+ # The desired target version.
52
+ #
53
+ # @api semipublic
54
+ #
55
+ def self.migrate(target_version=nil)
56
+ context.migrate(target_version)
57
+ end
58
+
59
+ #
60
+ # Explicitly migrates up the database to the target version.
61
+ #
62
+ # @param [Integer, nil] target_version
63
+ # The desired target version.
64
+ #
65
+ # @api semipublic
66
+ #
67
+ def self.up(target_version=nil,&block)
68
+ context.up(target_version,&block)
69
+ end
70
+
71
+ #
72
+ # Explicitly migrates down the database to the target version.
73
+ #
74
+ # @param [Integer, nil] target_version
75
+ # The desired target version.
76
+ #
77
+ # @api semipublic
78
+ #
79
+ def self.down(target_version=nil,&block)
80
+ context.down(target_version,&block)
81
+ end
82
+
83
+ #
84
+ # Rollbacks the last number of migrations.
85
+ #
86
+ # @param [Integer] steps
87
+ # The number of migrations to rollback.
88
+ #
89
+ # @api semipublic
90
+ #
91
+ def self.rollback(steps=1)
92
+ context.rollback(steps)
93
+ end
94
+
95
+ #
96
+ # Applies the next number of migrations.
97
+ #
98
+ # @param [Integer] steps
99
+ # The number of migrations to rollback.
100
+ #
101
+ # @api semipublic
102
+ #
103
+ def self.foreward(steps=1)
104
+ context.foreward(steps)
105
+ end
106
+
107
+ private
108
+
109
+ # Path to the `db/migrate/` directory in `ronin-db-activerecord`.
110
+ DIR = File.expand_path('../../../db/migrate',__dir__)
111
+
112
+ #
113
+ # Extensions `ActiveRecord::MigrationContext` to load our migrations from
114
+ # the `db/migrate/` directory and update our
115
+ # `ronin_schema_migration` table.
116
+ #
117
+ # @api private
118
+ #
119
+ class MigrationContext < ActiveRecord::MigrationContext
120
+
121
+ def initialize
122
+ super([Ronin::DB::Migrations::DIR],Ronin::DB::SchemaMigration)
123
+ end
124
+
125
+ end
126
+
127
+ #
128
+ # The migration context.
129
+ #
130
+ # @return [MigrationContext]
131
+ #
132
+ def self.context
133
+ @migrations ||= MigrationContext.new
134
+ end
135
+ end
136
+ end
137
+ end