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.
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,104 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/http_query_param'
3
+ require 'ronin/db/http_request'
4
+
5
+ describe Ronin::DB::HTTPQueryParam do
6
+ it "must use the 'ronin_http_query_params' table" do
7
+ expect(described_class.table_name).to eq('ronin_http_query_params')
8
+ end
9
+
10
+ let(:name) { 'foo' }
11
+ let(:value) { 'bar' }
12
+
13
+ let(:http_query_param_name) do
14
+ Ronin::DB::HTTPQueryParamName.find_or_initialize_by(name: name)
15
+ end
16
+
17
+ let(:request_method) { :get }
18
+ let(:path) { '/search' }
19
+ let(:request) do
20
+ Ronin::DB::HTTPRequest.new(
21
+ request_method: request_method,
22
+ path: path
23
+ )
24
+ end
25
+
26
+ describe "validations" do
27
+ describe "name" do
28
+ it "must require a name association" do
29
+ http_query_param = described_class.new(value: value)
30
+ expect(http_query_param).to_not be_valid
31
+ expect(http_query_param.errors[:name]).to eq(
32
+ ["must exist"]
33
+ )
34
+
35
+ http_query_param = described_class.new(
36
+ name: http_query_param_name,
37
+ value: value,
38
+ request: request
39
+ )
40
+ expect(http_query_param).to be_valid
41
+ end
42
+ end
43
+
44
+ describe "request" do
45
+ it "must require a request association" do
46
+ http_query_param = described_class.new(
47
+ name: http_query_param_name,
48
+ value: value
49
+ )
50
+
51
+ expect(http_query_param).to_not be_valid
52
+ expect(http_query_param.errors[:request]).to eq(
53
+ ['must exist']
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ subject do
60
+ described_class.new(
61
+ name: Ronin::DB::HTTPQueryParamName.new(name: name),
62
+ value: value,
63
+ request: request
64
+ )
65
+ end
66
+
67
+ describe "#to_s" do
68
+ it "should dump a name and a value into a String" do
69
+ expect(subject.to_s).to eq("#{name}=#{value}")
70
+ end
71
+
72
+ context "when an empty value" do
73
+ let(:value) { '' }
74
+
75
+ it "should ignore empty or nil values" do
76
+ expect(subject.to_s).to eq("#{name}=")
77
+ end
78
+ end
79
+
80
+ context "when a nil value" do
81
+ let(:value) { nil }
82
+
83
+ it "should ignore empty or nil values" do
84
+ expect(subject.to_s).to eq("#{name}=")
85
+ end
86
+ end
87
+
88
+ context "with special characters" do
89
+ let(:value) { 'bar baz' }
90
+ let(:encoded_value) { URI::DEFAULT_PARSER.escape(value) }
91
+
92
+ subject do
93
+ described_class.new(
94
+ name: Ronin::DB::HTTPQueryParamName.new(name: name),
95
+ value: value
96
+ )
97
+ end
98
+
99
+ it "should escape special characters" do
100
+ expect(subject.to_s).to eq("#{name}=#{encoded_value}")
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/http_request_header'
3
+ require 'ronin/db/http_request'
4
+
5
+ describe Ronin::DB::HTTPRequestHeader do
6
+ it "must use the 'ronin_http_request_headers' table" do
7
+ expect(described_class.table_name).to eq('ronin_http_request_headers')
8
+ end
9
+
10
+ let(:name) { 'foo' }
11
+ let(:value) { 'bar' }
12
+
13
+ let(:http_header_name) do
14
+ Ronin::DB::HTTPHeaderName.find_or_initialize_by(name: name)
15
+ end
16
+
17
+ let(:request_method) { :get }
18
+ let(:path) { '/search' }
19
+ let(:request) do
20
+ Ronin::DB::HTTPRequest.new(
21
+ request_method: request_method,
22
+ path: path
23
+ )
24
+ end
25
+
26
+ describe "validations" do
27
+ describe "name" do
28
+ it "must require a name association" do
29
+ http_request_header = described_class.new(value: value)
30
+ expect(http_request_header).to_not be_valid
31
+ expect(http_request_header.errors[:name]).to eq(
32
+ ["must exist"]
33
+ )
34
+
35
+ http_request_header = described_class.new(
36
+ name: http_header_name,
37
+ value: value,
38
+ request: request
39
+ )
40
+ expect(http_request_header).to be_valid
41
+ end
42
+ end
43
+
44
+ describe "request" do
45
+ it "must require a request association" do
46
+ http_request_header = described_class.new(
47
+ name: http_header_name,
48
+ value: value
49
+ )
50
+
51
+ expect(http_request_header).to_not be_valid
52
+ expect(http_request_header.errors[:request]).to eq(
53
+ ['must exist']
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ subject do
60
+ described_class.new(
61
+ name: Ronin::DB::HTTPHeaderName.new(name: name),
62
+ value: value,
63
+ request: request
64
+ )
65
+ end
66
+
67
+ describe "#to_s" do
68
+ it "should dump a name and a value into a String" do
69
+ expect(subject.to_s).to eq("#{name}: #{value}")
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/http_request'
3
+
4
+ describe Ronin::DB::HTTPRequest do
5
+ it "must use the 'ronin_http_requests' table" do
6
+ expect(described_class.table_name).to eq('ronin_http_requests')
7
+ end
8
+
9
+ let(:name) { 'foo' }
10
+ let(:value) { 'bar' }
11
+
12
+ let(:http_header_name) do
13
+ Ronin::DB::HTTPHeaderName.find_or_initialize_by(name: name)
14
+ end
15
+
16
+ let(:version) { '1.1' }
17
+ let(:request_method) { :get }
18
+ let(:path) { '/search' }
19
+
20
+ subject do
21
+ described_class.new(
22
+ version: version,
23
+ request_method: request_method,
24
+ path: path
25
+ )
26
+ end
27
+
28
+ describe "validations" do
29
+ describe "version" do
30
+ %w[1.0 1.1 2.0].each do |valid_version|
31
+ it "must accept '#{valid_version}'" do
32
+ request = described_class.new(
33
+ version: valid_version,
34
+ request_method: request_method,
35
+ path: path
36
+ )
37
+
38
+ expect(request).to be_valid
39
+ end
40
+ end
41
+
42
+ it "must not accept any other version String" do
43
+ request = described_class.new(
44
+ version: '3.0',
45
+ request_method: request_method,
46
+ path: path
47
+ )
48
+
49
+ expect(request).to_not be_valid
50
+ expect(request.errors[:version]).to eq(
51
+ ["is not included in the list"]
52
+ )
53
+ end
54
+
55
+ it "must not accept any other String" do
56
+ request = described_class.new(
57
+ version: 'foo',
58
+ request_method: request_method,
59
+ path: path
60
+ )
61
+
62
+ expect(request).to_not be_valid
63
+ expect(request.errors[:version]).to eq(
64
+ ["is not included in the list"]
65
+ )
66
+ end
67
+
68
+ it "must not accept nil" do
69
+ request = described_class.new(
70
+ version: nil,
71
+ request_method: request_method,
72
+ path: path
73
+ )
74
+
75
+ expect(request).to_not be_valid
76
+ expect(request.errors[:version]).to eq(
77
+ ["can't be blank", "is not included in the list"]
78
+ )
79
+ end
80
+ end
81
+
82
+ describe "request_method" do
83
+ [
84
+ :copy,
85
+ :delete,
86
+ :get,
87
+ :head,
88
+ :lock,
89
+ :mkcol,
90
+ :move,
91
+ :options,
92
+ :patch,
93
+ :post,
94
+ :propfind,
95
+ :proppatch,
96
+ :put,
97
+ :trace,
98
+ :unlock
99
+ ].each do |valid_request_method|
100
+ it "must accept #{valid_request_method.inspect}" do
101
+ request = described_class.new(
102
+ version: version,
103
+ request_method: valid_request_method,
104
+ path: path
105
+ )
106
+
107
+ expect(request).to be_valid
108
+ end
109
+ end
110
+
111
+ it "must not accept any other Symbol" do
112
+ expect {
113
+ described_class.new(
114
+ version: version,
115
+ request_method: :foo,
116
+ path: path
117
+ )
118
+ }.to raise_error(ArgumentError,"'foo' is not a valid request_method")
119
+ end
120
+
121
+ it "must not accept a nil value" do
122
+ request = described_class.new(
123
+ version: version,
124
+ request_method: nil,
125
+ path: path
126
+ )
127
+
128
+ expect(request).to_not be_valid
129
+ end
130
+
131
+ it "must require a request_method value" do
132
+ request = described_class.new(
133
+ version: version,
134
+ path: path
135
+ )
136
+
137
+ expect(request).to_not be_valid
138
+ end
139
+ end
140
+
141
+ describe "path" do
142
+ it "must require a path" do
143
+ request = described_class.new(
144
+ version: version,
145
+ request_method: request_method
146
+ )
147
+
148
+ expect(request).to_not be_valid
149
+ expect(request.errors[:path]).to eq(
150
+ ["can't be blank"]
151
+ )
152
+ end
153
+
154
+ it "must require a non-empty path" do
155
+ request = described_class.new(
156
+ version: version,
157
+ request_method: request_method,
158
+ path: ''
159
+ )
160
+
161
+ expect(request).to_not be_valid
162
+ expect(request.errors[:path]).to eq(
163
+ ["can't be blank"]
164
+ )
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/http_response_header'
3
+ require 'ronin/db/http_response'
4
+
5
+ describe Ronin::DB::HTTPResponseHeader do
6
+ it "must use the 'ronin_http_response_headers' table" do
7
+ expect(described_class.table_name).to eq('ronin_http_response_headers')
8
+ end
9
+
10
+ let(:name) { 'foo' }
11
+ let(:value) { 'bar' }
12
+
13
+ let(:http_header_name) do
14
+ Ronin::DB::HTTPHeaderName.find_or_initialize_by(name: name)
15
+ end
16
+
17
+ let(:request_method) { :get }
18
+ let(:path) { '/search' }
19
+ let(:request) do
20
+ Ronin::DB::HTTPRequest.new(
21
+ request_method: request_method,
22
+ path: path,
23
+ respnse: response
24
+ )
25
+ end
26
+ let(:response) { Ronin::DB::HTTPResponse.new }
27
+
28
+ describe "validations" do
29
+ describe "name" do
30
+ it "must require a name association" do
31
+ http_response_header = described_class.new(value: value)
32
+ expect(http_response_header).to_not be_valid
33
+ expect(http_response_header.errors[:name]).to eq(
34
+ ["must exist"]
35
+ )
36
+
37
+ http_response_header = described_class.new(
38
+ name: http_header_name,
39
+ value: value,
40
+ response: response
41
+ )
42
+ expect(http_response_header).to be_valid
43
+ end
44
+ end
45
+
46
+ describe "response" do
47
+ it "must require a response association" do
48
+ http_response_header = described_class.new(
49
+ name: http_header_name,
50
+ value: value
51
+ )
52
+
53
+ expect(http_response_header).to_not be_valid
54
+ expect(http_response_header.errors[:response]).to eq(
55
+ ['must exist']
56
+ )
57
+ end
58
+ end
59
+ end
60
+
61
+ subject do
62
+ described_class.new(
63
+ name: Ronin::DB::HTTPHeaderName.new(name: name),
64
+ value: value,
65
+ response: response
66
+ )
67
+ end
68
+
69
+ describe "#to_s" do
70
+ it "should dump a name and a value into a String" do
71
+ expect(subject.to_s).to eq("#{name}: #{value}")
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/http_response'
3
+
4
+ describe Ronin::DB::HTTPResponse do
5
+ it "must use the 'ronin_http_responses' table" do
6
+ expect(described_class.table_name).to eq('ronin_http_responses')
7
+ end
8
+
9
+ let(:name) { 'foo' }
10
+ let(:value) { 'bar' }
11
+
12
+ let(:http_header_name) do
13
+ Ronin::DB::HTTPHeaderName.find_or_initialize_by(name: name)
14
+ end
15
+
16
+ let(:version) { '1.1' }
17
+ let(:request_method) { :get }
18
+ let(:path) { '/search' }
19
+
20
+ let(:request) do
21
+ Ronin::DB::HTTPRequest.new(
22
+ version: version,
23
+ request_method: request_method,
24
+ path: path
25
+ )
26
+ end
27
+
28
+ let(:status) { 200 }
29
+ subject do
30
+ described_class.new(
31
+ status: status,
32
+ request: request
33
+ )
34
+ end
35
+
36
+ describe "validations" do
37
+ describe "status" do
38
+ it "must require a status" do
39
+ response = described_class.new(request: request)
40
+
41
+ expect(response).to_not be_valid
42
+ expect(response.errors[:status]).to eq(
43
+ ["can't be blank", "is not included in the list"]
44
+ )
45
+ end
46
+
47
+ it "must not allow nil" do
48
+ response = described_class.new(
49
+ status: nil,
50
+ request: request
51
+ )
52
+
53
+ expect(response).to_not be_valid
54
+ expect(response.errors[:status]).to eq(
55
+ ["can't be blank", "is not included in the list"]
56
+ )
57
+ end
58
+
59
+ [
60
+ 100, 101, 103,
61
+ 200, 201, 202, 203, 204, 206, 207, 208, 226,
62
+ 300, 301, 302, 303, 304, 305, 306, 307, 308,
63
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
64
+ 410, 411, 412, 413, 414, 415, 416, 417, 418,
65
+ 421, 422, 423, 424, 425, 426, 428, 429,
66
+ 431, 451,
67
+ 500, 501, 502, 503, 504, 505, 506, 507, 508, 511
68
+ ].each do |valid_status|
69
+ it "must accept #{valid_status}" do
70
+ response = described_class.new(
71
+ status: valid_status,
72
+ request: request
73
+ )
74
+
75
+ expect(response).to be_valid
76
+ end
77
+ end
78
+
79
+ it "must not accept any other Integer" do
80
+ response = described_class.new(
81
+ status: 600,
82
+ request: request
83
+ )
84
+
85
+ expect(response).to_not be_valid
86
+ expect(response.errors[:status]).to eq(
87
+ ["is not included in the list"]
88
+ )
89
+ end
90
+ end
91
+
92
+ describe "request" do
93
+ it "must require a parent request" do
94
+ response = described_class.new(status: status)
95
+
96
+ expect(response).to_not be_valid
97
+ expect(response.errors[:request]).to eq(
98
+ ["must exist"]
99
+ )
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'ronin/db/ip_address_mac_address'
3
+
4
+ describe Ronin::DB::IPAddressMACAddress do
5
+ it "must use the 'ronin_ip_addresses_mac_address' table" do
6
+ expect(described_class.table_name).to eq('ronin_ip_address_mac_addresses')
7
+ end
8
+ end