ronin-db-activerecord 0.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +39 -0
- data/Gemfile +27 -0
- data/README.md +143 -0
- data/Rakefile +72 -0
- data/db/migrate/0001_create_ronin_ip_address_mac_addresses_table.rb +43 -0
- data/db/migrate/0002_create_ronin_vulnerabilities_table.rb +61 -0
- data/db/migrate/0003_create_ronin_url_schemes_table.rb +32 -0
- data/db/migrate/0004_create_ronin_url_query_param_names_table.rb +32 -0
- data/db/migrate/0005_create_ronin_user_names_table.rb +33 -0
- data/db/migrate/0006_create_ronin_software_vendors_table.rb +32 -0
- data/db/migrate/0007_create_ronin_advisories_table.rb +42 -0
- data/db/migrate/0008_create_ronin_host_name_ip_addresses_table.rb +43 -0
- data/db/migrate/0009_create_ronin_host_names_table.rb +34 -0
- data/db/migrate/0010_create_ronin_arches_table.rb +37 -0
- data/db/migrate/0011_create_ronin_email_addresses_table.rb +44 -0
- data/db/migrate/0012_create_ronin_oses_table.rb +36 -0
- data/db/migrate/0013_create_ronin_organizations_table.rb +31 -0
- data/db/migrate/0014_create_ronin_ip_addresses_table.rb +35 -0
- data/db/migrate/0015_create_ronin_os_guesses_table.rb +40 -0
- data/db/migrate/0016_create_ronin_url_query_params_table.rb +42 -0
- data/db/migrate/0017_create_ronin_passwords_table.rb +32 -0
- data/db/migrate/0018_create_ronin_open_ports_table.rb +46 -0
- data/db/migrate/0019_create_ronin_urls_table.rb +50 -0
- data/db/migrate/0020_create_ronin_softwares_table.rb +39 -0
- data/db/migrate/0021_create_ronin_mac_addresses_table.rb +33 -0
- data/db/migrate/0022_create_ronin_countries_table.rb +34 -0
- data/db/migrate/0023_create_ronin_services_table.rb +32 -0
- data/db/migrate/0024_create_ronin_credentials_table.rb +44 -0
- data/db/migrate/0025_create_ronin_ports_table.rb +33 -0
- data/db/migrate/0026_create_ronin_asns_table.rb +44 -0
- data/db/migrate/0027_create_ronin_http_query_param_names_table.rb +32 -0
- data/db/migrate/0028_create_ronin_http_query_params_table.rb +42 -0
- data/db/migrate/0029_create_ronin_http_header_names_table.rb +31 -0
- data/db/migrate/0030_create_ronin_http_request_headers_table.rb +41 -0
- data/db/migrate/0031_create_ronin_http_response_headers_table.rb +41 -0
- data/db/migrate/0032_create_ronin_http_requests_table.rb +41 -0
- data/db/migrate/0033_create_ronin_http_responses_table.rb +36 -0
- data/db/migrate/0034_create_ronin_service_credentials_table.rb +41 -0
- data/db/migrate/0035_create_ronin_web_credentials_table.rb +41 -0
- data/gemspec.yml +28 -0
- data/lib/ronin/db/address.rb +105 -0
- data/lib/ronin/db/advisory.rb +169 -0
- data/lib/ronin/db/arch.rb +160 -0
- data/lib/ronin/db/asn.rb +212 -0
- data/lib/ronin/db/credential.rb +248 -0
- data/lib/ronin/db/email_address.rb +225 -0
- data/lib/ronin/db/host_name.rb +224 -0
- data/lib/ronin/db/host_name_ip_address.rb +65 -0
- data/lib/ronin/db/http_header_name.rb +75 -0
- data/lib/ronin/db/http_query_param.rb +79 -0
- data/lib/ronin/db/http_query_param_name.rb +76 -0
- data/lib/ronin/db/http_request.rb +120 -0
- data/lib/ronin/db/http_request_header.rb +78 -0
- data/lib/ronin/db/http_response.rb +91 -0
- data/lib/ronin/db/http_response_header.rb +78 -0
- data/lib/ronin/db/ip_address.rb +351 -0
- data/lib/ronin/db/ip_address_mac_address.rb +62 -0
- data/lib/ronin/db/mac_address.rb +91 -0
- data/lib/ronin/db/migrations.rb +137 -0
- data/lib/ronin/db/model/has_name.rb +102 -0
- data/lib/ronin/db/model/has_unique_name.rb +82 -0
- data/lib/ronin/db/model/importable.rb +85 -0
- data/lib/ronin/db/model/last_scanned_at.rb +48 -0
- data/lib/ronin/db/model.rb +37 -0
- data/lib/ronin/db/models.rb +108 -0
- data/lib/ronin/db/open_port.rb +148 -0
- data/lib/ronin/db/organization.rb +50 -0
- data/lib/ronin/db/os.rb +183 -0
- data/lib/ronin/db/os_guess.rb +67 -0
- data/lib/ronin/db/password.rb +167 -0
- data/lib/ronin/db/port.rb +123 -0
- data/lib/ronin/db/root.rb +28 -0
- data/lib/ronin/db/schema_migration.rb +34 -0
- data/lib/ronin/db/service.rb +48 -0
- data/lib/ronin/db/service_credential.rb +66 -0
- data/lib/ronin/db/software.rb +85 -0
- data/lib/ronin/db/software_vendor.rb +42 -0
- data/lib/ronin/db/url.rb +497 -0
- data/lib/ronin/db/url_query_param.rb +79 -0
- data/lib/ronin/db/url_query_param_name.rb +76 -0
- data/lib/ronin/db/url_scheme.rb +80 -0
- data/lib/ronin/db/user_name.rb +96 -0
- data/lib/ronin/db/vulnerability.rb +81 -0
- data/lib/ronin/db/web_credential.rb +69 -0
- data/ronin-db-activerecord.gemspec +61 -0
- data/spec/advisory_spec.rb +277 -0
- data/spec/arch_spec.rb +228 -0
- data/spec/asn_spec.rb +504 -0
- data/spec/credential_spec.rb +362 -0
- data/spec/email_address_spec.rb +372 -0
- data/spec/host_name_ip_address_spec.rb +8 -0
- data/spec/host_name_spec.rb +207 -0
- data/spec/http_header_name_spec.rb +25 -0
- data/spec/http_query_param_name_spec.rb +25 -0
- data/spec/http_query_param_spec.rb +104 -0
- data/spec/http_request_header_spec.rb +72 -0
- data/spec/http_request_spec.rb +168 -0
- data/spec/http_response_header_spec.rb +74 -0
- data/spec/http_response_spec.rb +103 -0
- data/spec/ip_address_mac_addresses_spec.rb +8 -0
- data/spec/ip_address_spec.rb +386 -0
- data/spec/mac_address_spec.rb +67 -0
- data/spec/migrations_spec.rb +122 -0
- data/spec/model/has_name_spec.rb +65 -0
- data/spec/model/has_unique_name_spec.rb +61 -0
- data/spec/model/importable_spec.rb +105 -0
- data/spec/models_spec.rb +60 -0
- data/spec/open_port_spec.rb +87 -0
- data/spec/organization_spec.rb +10 -0
- data/spec/os_guess_spec.rb +43 -0
- data/spec/os_spec.rb +114 -0
- data/spec/password_spec.rb +81 -0
- data/spec/port_spec.rb +102 -0
- data/spec/schema_migration_spec.rb +8 -0
- data/spec/service_credential_spec.rb +43 -0
- data/spec/service_spec.rb +39 -0
- data/spec/software_spec.rb +76 -0
- data/spec/software_vendor_spec.rb +33 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/url_query_param_name_spec.rb +25 -0
- data/spec/url_query_param_spec.rb +110 -0
- data/spec/url_scheme_spec.rb +39 -0
- data/spec/url_spec.rb +951 -0
- data/spec/user_name_spec.rb +54 -0
- data/spec/vulnerability_spec.rb +8 -0
- data/spec/web_credential_spec.rb +72 -0
- metadata +266 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'ronin/db/ip_address'
|
|
4
|
+
|
|
5
|
+
describe Ronin::DB::IPAddress do
|
|
6
|
+
it "must use the 'ronin_ip_addresses' table" do
|
|
7
|
+
expect(described_class.table_name).to eq('ronin_ip_addresses')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:address) { '127.0.0.1' }
|
|
11
|
+
|
|
12
|
+
let(:ipv4_address) { '93.184.216.34' }
|
|
13
|
+
let(:ipv6_address) { '2606:2800:220:1:248:1893:25c8:1946' }
|
|
14
|
+
|
|
15
|
+
subject { described_class.new(address: address) }
|
|
16
|
+
|
|
17
|
+
describe "validations" do
|
|
18
|
+
describe "address" do
|
|
19
|
+
it "must require an address" do
|
|
20
|
+
ip_address = described_class.new
|
|
21
|
+
expect(ip_address).to_not be_valid
|
|
22
|
+
|
|
23
|
+
ip_address = described_class.new(address: address)
|
|
24
|
+
expect(ip_address).to be_valid
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "must accept IPv4 addresses" do
|
|
28
|
+
ip_address = described_class.new(address: ipv4_address)
|
|
29
|
+
expect(ip_address).to be_valid
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "must accept IPv6 addresses" do
|
|
33
|
+
ip_address = described_class.new(address: ipv6_address)
|
|
34
|
+
expect(ip_address).to be_valid
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "must not accept non-IP addresses" do
|
|
38
|
+
ip_address = described_class.new(address: '0')
|
|
39
|
+
expect(ip_address).to_not be_valid
|
|
40
|
+
expect(ip_address.errors[:address]).to eq(
|
|
41
|
+
["Must be a valid IP address"]
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe ".v4" do
|
|
48
|
+
subject { described_class }
|
|
49
|
+
|
|
50
|
+
before do
|
|
51
|
+
subject.create(address: ipv4_address)
|
|
52
|
+
subject.create(address: ipv6_address)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "must query all #{described_class} with IPv4 addresses" do
|
|
56
|
+
ip_addresses = subject.v4
|
|
57
|
+
expect(ip_addresses.count).to eq(1)
|
|
58
|
+
|
|
59
|
+
ip_address = ip_addresses.first
|
|
60
|
+
expect(ip_address).to be_kind_of(described_class)
|
|
61
|
+
expect(ip_address.address).to eq(ipv4_address)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
after do
|
|
65
|
+
subject.destroy_all
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe ".v6" do
|
|
70
|
+
subject { described_class }
|
|
71
|
+
|
|
72
|
+
before do
|
|
73
|
+
subject.create(address: ipv4_address)
|
|
74
|
+
subject.create(address: ipv6_address)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "must query all #{described_class} with IPv6 addresses" do
|
|
78
|
+
ip_addresses = subject.v6
|
|
79
|
+
expect(ip_addresses.count).to eq(1)
|
|
80
|
+
|
|
81
|
+
ip_address = ip_addresses.first
|
|
82
|
+
expect(ip_address).to be_kind_of(described_class)
|
|
83
|
+
expect(ip_address.address).to eq(ipv6_address)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
after do
|
|
87
|
+
subject.destroy_all
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe ".between" do
|
|
92
|
+
subject { described_class }
|
|
93
|
+
|
|
94
|
+
let(:address1) { '4.1.1.1' }
|
|
95
|
+
let(:address2) { '4.2.2.2' }
|
|
96
|
+
let(:address3) { '4.3.3.3' }
|
|
97
|
+
|
|
98
|
+
before do
|
|
99
|
+
described_class.create(address: '4.0.0.0')
|
|
100
|
+
described_class.create(address: address1)
|
|
101
|
+
described_class.create(address: address2)
|
|
102
|
+
described_class.create(address: address3)
|
|
103
|
+
described_class.create(address: '4.4.4.4')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "must query all IP addresses that are in between the first and last IP address" do
|
|
107
|
+
ip_addresses = subject.between(address1,address3)
|
|
108
|
+
|
|
109
|
+
expect(ip_addresses.length).to eq(3)
|
|
110
|
+
expect(ip_addresses).to all(be_kind_of(described_class))
|
|
111
|
+
expect(ip_addresses[0].address).to eq(address1)
|
|
112
|
+
expect(ip_addresses[1].address).to eq(address2)
|
|
113
|
+
expect(ip_addresses[2].address).to eq(address3)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
after { described_class.destroy_all }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe ".in_range" do
|
|
120
|
+
subject { described_class }
|
|
121
|
+
|
|
122
|
+
let(:address1) { '4.1.1.1' }
|
|
123
|
+
let(:address2) { '4.2.2.2' }
|
|
124
|
+
let(:address3) { '4.3.3.3' }
|
|
125
|
+
let(:range) { address1..address3 }
|
|
126
|
+
|
|
127
|
+
before do
|
|
128
|
+
described_class.create(address: '4.0.0.0')
|
|
129
|
+
described_class.create(address: address1)
|
|
130
|
+
described_class.create(address: address2)
|
|
131
|
+
described_class.create(address: address3)
|
|
132
|
+
described_class.create(address: '4.4.4.4')
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "must query all IP addresses that are in between the first and last IP address" do
|
|
136
|
+
ip_addresses = subject.in_range(range)
|
|
137
|
+
|
|
138
|
+
expect(ip_addresses.length).to eq(3)
|
|
139
|
+
expect(ip_addresses).to all(be_kind_of(described_class))
|
|
140
|
+
expect(ip_addresses[0].address).to eq(address1)
|
|
141
|
+
expect(ip_addresses[1].address).to eq(address2)
|
|
142
|
+
expect(ip_addresses[2].address).to eq(address3)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
after { described_class.destroy_all }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe ".with_mac_address" do
|
|
149
|
+
subject { described_class }
|
|
150
|
+
|
|
151
|
+
let(:mac_address) { '00:01:02:03:04:05' }
|
|
152
|
+
|
|
153
|
+
before do
|
|
154
|
+
ip_address = subject.create(address: address)
|
|
155
|
+
ip_address.mac_addresses.create(address: mac_address)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "must query all #{described_class} with the associated MAC address" do
|
|
159
|
+
ip_addresses = subject.with_mac_address(mac_address)
|
|
160
|
+
expect(ip_addresses.count).to eq(1)
|
|
161
|
+
|
|
162
|
+
ip_address = ip_addresses.first
|
|
163
|
+
expect(ip_address.mac_addresses.first.address).to eq(mac_address)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
after do
|
|
167
|
+
Ronin::DB::IPAddressMACAddress.destroy_all
|
|
168
|
+
Ronin::DB::IPAddress.destroy_all
|
|
169
|
+
Ronin::DB::MACAddress.destroy_all
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe ".with_host_name" do
|
|
174
|
+
subject { described_class }
|
|
175
|
+
|
|
176
|
+
let(:host) { 'example.com' }
|
|
177
|
+
|
|
178
|
+
before do
|
|
179
|
+
ip_address = subject.create(address: address)
|
|
180
|
+
ip_address.host_names.create(name: host)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it "must query all #{described_class} with the associated host name" do
|
|
184
|
+
ip_addresses = subject.with_host_name(host)
|
|
185
|
+
expect(ip_addresses.count).to eq(1)
|
|
186
|
+
|
|
187
|
+
ip_address = ip_addresses.first
|
|
188
|
+
expect(ip_address.host_names.first.name).to eq(host)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
after do
|
|
192
|
+
Ronin::DB::HostNameIPAddress.destroy_all
|
|
193
|
+
Ronin::DB::IPAddress.destroy_all
|
|
194
|
+
Ronin::DB::HostName.destroy_all
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
describe ".with_port_number" do
|
|
199
|
+
subject { described_class }
|
|
200
|
+
|
|
201
|
+
let(:port) { 443 }
|
|
202
|
+
|
|
203
|
+
before do
|
|
204
|
+
ip_address = subject.create(address: address)
|
|
205
|
+
ip_address.ports.create(protocol: :tcp, number: 80)
|
|
206
|
+
ip_address.ports.create(protocol: :tcp, number: port)
|
|
207
|
+
ip_address.ports.create(protocol: :tcp, number: 8080)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "must query all #{described_class} with the associated port number" do
|
|
211
|
+
ip_addresses = subject.with_port_number(port)
|
|
212
|
+
expect(ip_addresses.count).to eq(1)
|
|
213
|
+
|
|
214
|
+
ip_address = ip_addresses.first
|
|
215
|
+
expect(ip_address.ports[1].number).to eq(port)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
after do
|
|
219
|
+
Ronin::DB::OpenPort.destroy_all
|
|
220
|
+
Ronin::DB::IPAddress.destroy_all
|
|
221
|
+
Ronin::DB::Port.destroy_all
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
describe ".lookup" do
|
|
226
|
+
before do
|
|
227
|
+
described_class.create(address: '1.2.4.5')
|
|
228
|
+
described_class.create(address: address)
|
|
229
|
+
described_class.create(address: '6.7.8.9')
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "must query the #{described_class} with the matching IP address" do
|
|
233
|
+
ip_address = described_class.lookup(address)
|
|
234
|
+
|
|
235
|
+
expect(ip_address).to be_kind_of(described_class)
|
|
236
|
+
expect(ip_address.address).to eq(address)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
after { described_class.destroy_all }
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
describe ".import" do
|
|
243
|
+
subject { described_class.import(address) }
|
|
244
|
+
|
|
245
|
+
it "must parse and import the IP address and set #address" do
|
|
246
|
+
expect(subject).to be_kind_of(described_class)
|
|
247
|
+
expect(subject.id).to_not be(nil)
|
|
248
|
+
expect(subject.address).to eq(address)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
after { described_class.destroy_all }
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
describe "#ipaddr" do
|
|
255
|
+
it "must automatically parse #address and return an IPAddr" do
|
|
256
|
+
expect(subject.ipaddr).to be_kind_of(IPAddr)
|
|
257
|
+
expect(subject.ipaddr.to_s).to eq(address)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
context "when the address is an IPv4 address" do
|
|
261
|
+
let(:address) { ipv4_address }
|
|
262
|
+
|
|
263
|
+
it "must return an IPv4 IPAddr" do
|
|
264
|
+
expect(subject.ipaddr.ipv4?).to be(true)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
context "when the address is an IPv6 address" do
|
|
269
|
+
let(:address) { ipv6_address }
|
|
270
|
+
|
|
271
|
+
it "must return an IPv6 IPAddr" do
|
|
272
|
+
expect(subject.ipaddr.ipv6?).to be(true)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context "when the address is not a valid IP address" do
|
|
277
|
+
let(:address) { '0' }
|
|
278
|
+
|
|
279
|
+
it "must return nil" do
|
|
280
|
+
expect(subject.ipaddr).to be(nil)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
describe "#version" do
|
|
286
|
+
it "should only accept 4 or 6" do
|
|
287
|
+
ip_address = described_class.new(address: '1.1.1.1', version: 7)
|
|
288
|
+
|
|
289
|
+
expect(ip_address).not_to be_valid
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
context "with IPv4 address" do
|
|
293
|
+
subject { described_class.new(address: '127.0.0.1') }
|
|
294
|
+
|
|
295
|
+
it { expect(subject.version).to be == 4 }
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
context "with IPv6 address" do
|
|
299
|
+
subject { described_class.new(address: '::1') }
|
|
300
|
+
|
|
301
|
+
it { expect(subject.version).to be == 6 }
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
describe "#asn" do
|
|
306
|
+
let(:asn_version) { 4 }
|
|
307
|
+
let(:asn_range_start) { '4.0.0.0' }
|
|
308
|
+
let(:asn_range_end) { '4.7.168.255' }
|
|
309
|
+
let(:asn_number) { 3356 }
|
|
310
|
+
let(:asn_country_code) { 'US' }
|
|
311
|
+
let(:asn_name) { 'LEVEL3' }
|
|
312
|
+
|
|
313
|
+
before do
|
|
314
|
+
Ronin::DB::ASN.create(
|
|
315
|
+
version: 6,
|
|
316
|
+
range_start: '64:ff9b::1:0:0',
|
|
317
|
+
range_end: '100::ffff:ffff:ffff:ffff',
|
|
318
|
+
number: 0
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
Ronin::DB::ASN.create(
|
|
322
|
+
version: asn_version,
|
|
323
|
+
range_start: asn_range_start,
|
|
324
|
+
range_end: asn_range_end,
|
|
325
|
+
number: asn_number,
|
|
326
|
+
country_code: asn_country_code,
|
|
327
|
+
name: asn_name
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
Ronin::DB::ASN.create(
|
|
331
|
+
version: 6,
|
|
332
|
+
range_start: '::',
|
|
333
|
+
range_end: '::1',
|
|
334
|
+
number: 0
|
|
335
|
+
)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
let(:version) { 4 }
|
|
339
|
+
let(:address) { '4.4.4.4' }
|
|
340
|
+
|
|
341
|
+
subject do
|
|
342
|
+
described_class.new(
|
|
343
|
+
version: version,
|
|
344
|
+
address: address
|
|
345
|
+
)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it "must lookup the ASN record containing the IP address" do
|
|
349
|
+
asn = subject.asn
|
|
350
|
+
|
|
351
|
+
expect(asn).to be_kind_of(Ronin::DB::ASN)
|
|
352
|
+
expect(asn.version).to eq(version)
|
|
353
|
+
expect(asn.range_start).to eq('4.0.0.0')
|
|
354
|
+
expect(asn.range_end).to eq('4.7.168.255')
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
after do
|
|
358
|
+
Ronin::DB::ASN.destroy_all
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
describe "#recent_mac_address" do
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
describe "#recent_host_name" do
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
describe "#recent_os_guess" do
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
describe "#save" do
|
|
372
|
+
subject { described_class.create(address: address) }
|
|
373
|
+
|
|
374
|
+
it "must set hton" do
|
|
375
|
+
expect(subject.hton).to eq(subject.ipaddr.hton)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
after { subject.destroy }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe "#to_ip" do
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
describe "#to_i" do
|
|
385
|
+
end
|
|
386
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/db/mac_address'
|
|
3
|
+
|
|
4
|
+
describe Ronin::DB::MACAddress do
|
|
5
|
+
it "must use the 'ronin_mac_addresses' table" do
|
|
6
|
+
expect(described_class.table_name).to eq('ronin_mac_addresses')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
let(:address) { '00:01:02:03:04:05' }
|
|
10
|
+
|
|
11
|
+
subject { described_class.new(address: address) }
|
|
12
|
+
|
|
13
|
+
describe "validations" do
|
|
14
|
+
describe "address" do
|
|
15
|
+
it "should require an address" do
|
|
16
|
+
mac_address = described_class.new
|
|
17
|
+
expect(mac_address).not_to be_valid
|
|
18
|
+
expect(mac_address.errors[:address]).to include(
|
|
19
|
+
"can't be blank"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
mac_address = described_class.new(address: address)
|
|
23
|
+
expect(mac_address).to be_valid
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe ".lookup" do
|
|
29
|
+
before do
|
|
30
|
+
described_class.create(address: '11:12:13:14:15:16')
|
|
31
|
+
described_class.create(address: address)
|
|
32
|
+
described_class.create(address: '21:22:23:24:25:26')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "must query the #{described_class} with the matching MAC address" do
|
|
36
|
+
ip_address = described_class.lookup(address)
|
|
37
|
+
|
|
38
|
+
expect(ip_address).to be_kind_of(described_class)
|
|
39
|
+
expect(ip_address.address).to eq(address)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
after { described_class.destroy_all }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe ".import" do
|
|
46
|
+
subject { described_class.import(address) }
|
|
47
|
+
|
|
48
|
+
it "must parse and import the MAC address and set #address" do
|
|
49
|
+
expect(subject).to be_kind_of(described_class)
|
|
50
|
+
expect(subject.id).to_not be(nil)
|
|
51
|
+
expect(subject.address).to eq(address)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
after { described_class.destroy_all }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#recent_ip_address" do
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#to_i" do
|
|
61
|
+
let(:integer) { 0x000102030405 }
|
|
62
|
+
|
|
63
|
+
it "should convert the MAC Address to an Integer" do
|
|
64
|
+
expect(subject.to_i).to eq(integer)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/db/migrations'
|
|
3
|
+
|
|
4
|
+
describe Ronin::DB::Migrations do
|
|
5
|
+
let(:migration_context) { subject.send(:context) }
|
|
6
|
+
|
|
7
|
+
describe ".current_version" do
|
|
8
|
+
it "must call .current_version on the MigrationContext object" do
|
|
9
|
+
expect(migration_context).to receive(:current_version)
|
|
10
|
+
|
|
11
|
+
subject.current_version
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe ".needs_migration?" do
|
|
16
|
+
it "must call .needs_migration? on the MigrationContext object" do
|
|
17
|
+
expect(migration_context).to receive(:needs_migration?)
|
|
18
|
+
|
|
19
|
+
subject.needs_migration?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe ".migrate" do
|
|
24
|
+
context "when called with no arguments" do
|
|
25
|
+
it "must call .migrate(nil) on the MigrationContext object" do
|
|
26
|
+
expect(migration_context).to receive(:migrate).with(nil)
|
|
27
|
+
|
|
28
|
+
subject.migrate
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context "when given a target version" do
|
|
33
|
+
let(:target_version) { 42 }
|
|
34
|
+
|
|
35
|
+
it "must call .migrate(target_version) on the MigrationContext object" do
|
|
36
|
+
expect(migration_context).to receive(:migrate).with(target_version)
|
|
37
|
+
|
|
38
|
+
subject.migrate(target_version)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe ".up" do
|
|
44
|
+
context "when called with no arguments" do
|
|
45
|
+
it "must call .up(nil) on the MigrationContext object" do
|
|
46
|
+
expect(migration_context).to receive(:up).with(nil)
|
|
47
|
+
|
|
48
|
+
subject.up
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "when given a target version" do
|
|
53
|
+
let(:target_version) { 42 }
|
|
54
|
+
|
|
55
|
+
it "must call .up(target_version) on the MigrationContext object" do
|
|
56
|
+
expect(migration_context).to receive(:up).with(target_version)
|
|
57
|
+
|
|
58
|
+
subject.up(target_version)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe ".down" do
|
|
64
|
+
context "when called with no arguments" do
|
|
65
|
+
it "must call .down(nil) on the MigrationContext object" do
|
|
66
|
+
expect(migration_context).to receive(:down).with(nil)
|
|
67
|
+
|
|
68
|
+
subject.down
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "when given a target version" do
|
|
73
|
+
let(:target_version) { 42 }
|
|
74
|
+
|
|
75
|
+
it "must call .down(target_version) on the MigrationContext object" do
|
|
76
|
+
expect(migration_context).to receive(:down).with(target_version)
|
|
77
|
+
|
|
78
|
+
subject.down(target_version)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe ".rollback" do
|
|
84
|
+
context "when called with no arguments" do
|
|
85
|
+
it "must call .rollback(1) on the MigrationContext object" do
|
|
86
|
+
expect(migration_context).to receive(:rollback).with(1)
|
|
87
|
+
|
|
88
|
+
subject.rollback
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context "when given a target version" do
|
|
93
|
+
let(:steps) { 2 }
|
|
94
|
+
|
|
95
|
+
it "must call .rollback(steps) on the MigrationContext object" do
|
|
96
|
+
expect(migration_context).to receive(:rollback).with(steps)
|
|
97
|
+
|
|
98
|
+
subject.rollback(steps)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe ".foreward" do
|
|
104
|
+
context "when called with no arguments" do
|
|
105
|
+
it "must call .foreward(1) on the MigrationContext object" do
|
|
106
|
+
expect(migration_context).to receive(:foreward).with(1)
|
|
107
|
+
|
|
108
|
+
subject.foreward
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context "when given a target version" do
|
|
113
|
+
let(:steps) { 2 }
|
|
114
|
+
|
|
115
|
+
it "must call .foreward(steps) on the MigrationContext object" do
|
|
116
|
+
expect(migration_context).to receive(:foreward).with(steps)
|
|
117
|
+
|
|
118
|
+
subject.foreward(steps)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/db/model/has_name'
|
|
3
|
+
|
|
4
|
+
describe Ronin::DB::Model::HasName do
|
|
5
|
+
class TestModelHasName < ActiveRecord::Base
|
|
6
|
+
include Ronin::DB::Model::HasName
|
|
7
|
+
|
|
8
|
+
self.table_name = 'test_model_has_name'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:model) { TestModelHasName }
|
|
12
|
+
|
|
13
|
+
before(:all) do
|
|
14
|
+
ActiveRecord::Base.connection.create_table :test_model_has_name do |t|
|
|
15
|
+
t.string :name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe ".included" do
|
|
20
|
+
subject { model }
|
|
21
|
+
|
|
22
|
+
it "should include Ronin::DB::Model" do
|
|
23
|
+
expect(subject.ancestors).to include(Ronin::DB::Model)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should define a name attribute" do
|
|
27
|
+
expect(subject.new).to respond_to(:name)
|
|
28
|
+
expect(subject.new).to respond_to(:name=)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "validations" do
|
|
33
|
+
subject { model }
|
|
34
|
+
|
|
35
|
+
it "should require a name" do
|
|
36
|
+
resource = subject.new
|
|
37
|
+
expect(resource).not_to be_valid
|
|
38
|
+
|
|
39
|
+
resource.name = 'foo'
|
|
40
|
+
expect(resource).to be_valid
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".named" do
|
|
45
|
+
subject { model }
|
|
46
|
+
|
|
47
|
+
let(:name1) { 'foo1' }
|
|
48
|
+
let(:name2) { 'foo2' }
|
|
49
|
+
|
|
50
|
+
before do
|
|
51
|
+
subject.create(name: name1)
|
|
52
|
+
subject.create(name: name2)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should be able to find resources with similar names" do
|
|
56
|
+
resources = subject.named('foo')
|
|
57
|
+
|
|
58
|
+
expect(resources.length).to eq(2)
|
|
59
|
+
expect(resources[0].name).to be == name1
|
|
60
|
+
expect(resources[1].name).to be == name2
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
after { subject.destroy_all }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'ronin/db/model/has_unique_name'
|
|
3
|
+
|
|
4
|
+
describe Ronin::DB::Model::HasUniqueName do
|
|
5
|
+
class TestModelHasUniqueName < ActiveRecord::Base
|
|
6
|
+
include Ronin::DB::Model::HasUniqueName
|
|
7
|
+
|
|
8
|
+
self.table_name = 'test_model_has_unique_name'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:model) { TestModelHasUniqueName }
|
|
12
|
+
|
|
13
|
+
before(:all) do
|
|
14
|
+
ActiveRecord::Base.connection.create_table :test_model_has_unique_name do |t|
|
|
15
|
+
t.string :name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe ".included" do
|
|
20
|
+
subject { model }
|
|
21
|
+
|
|
22
|
+
it "should include Ronin::DB::Model" do
|
|
23
|
+
expect(subject.ancestors).to include(Ronin::DB::Model)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should include Ronin::DB::Model::HasName::InstanceMethods" do
|
|
27
|
+
expect(subject.ancestors).to include(Ronin::DB::Model::HasName::InstanceMethods)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should define a name attribute" do
|
|
31
|
+
expect(subject.new).to respond_to(:name)
|
|
32
|
+
expect(subject.new).to respond_to(:name=)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "validations" do
|
|
37
|
+
subject { model }
|
|
38
|
+
|
|
39
|
+
it "should require a name" do
|
|
40
|
+
record = subject.new
|
|
41
|
+
expect(record).to_not be_valid
|
|
42
|
+
|
|
43
|
+
record.name = 'foo'
|
|
44
|
+
expect(record).to be_valid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when the given name already exists in the table" do
|
|
48
|
+
let(:name) { 'foo' }
|
|
49
|
+
|
|
50
|
+
before { model.create(name: name) }
|
|
51
|
+
|
|
52
|
+
it "must require a unique name" do
|
|
53
|
+
record = subject.new(name: name)
|
|
54
|
+
|
|
55
|
+
expect(record).to_not be_valid
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
after { model.destroy_all }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|