ronin-db 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +12 -0
- data/Gemfile +39 -0
- data/README.md +272 -0
- data/Rakefile +76 -0
- data/bin/ronin-db +35 -0
- data/gemspec.yml +46 -0
- data/lib/ronin/db/cli/command.rb +37 -0
- data/lib/ronin/db/cli/commands/add.rb +206 -0
- data/lib/ronin/db/cli/commands/asn.rb +218 -0
- data/lib/ronin/db/cli/commands/creds.rb +80 -0
- data/lib/ronin/db/cli/commands/edit.rb +58 -0
- data/lib/ronin/db/cli/commands/emails.rb +90 -0
- data/lib/ronin/db/cli/commands/hosts.rb +100 -0
- data/lib/ronin/db/cli/commands/ips.rb +100 -0
- data/lib/ronin/db/cli/commands/irb.rb +81 -0
- data/lib/ronin/db/cli/commands/list.rb +124 -0
- data/lib/ronin/db/cli/commands/migrate.rb +75 -0
- data/lib/ronin/db/cli/commands/remove.rb +69 -0
- data/lib/ronin/db/cli/commands/urls.rb +170 -0
- data/lib/ronin/db/cli/database_command.rb +71 -0
- data/lib/ronin/db/cli/model_command.rb +202 -0
- data/lib/ronin/db/cli/modifiable.rb +141 -0
- data/lib/ronin/db/cli/resources_command.rb +120 -0
- data/lib/ronin/db/cli/ruby_shell.rb +51 -0
- data/lib/ronin/db/cli/uri_methods.rb +97 -0
- data/lib/ronin/db/cli.rb +38 -0
- data/lib/ronin/db/config_file.rb +132 -0
- data/lib/ronin/db/exceptions.rb +26 -0
- data/lib/ronin/db/home.rb +36 -0
- data/lib/ronin/db/root.rb +28 -0
- data/lib/ronin/db/version.rb +26 -0
- data/lib/ronin/db.rb +123 -0
- data/man/ronin-db-add.1 +99 -0
- data/man/ronin-db-add.1.md +75 -0
- data/man/ronin-db-asn.1 +79 -0
- data/man/ronin-db-asn.1.md +59 -0
- data/man/ronin-db-creds.1 +78 -0
- data/man/ronin-db-creds.1.md +58 -0
- data/man/ronin-db-edit.1 +48 -0
- data/man/ronin-db-edit.1.md +36 -0
- data/man/ronin-db-emails.1 +82 -0
- data/man/ronin-db-emails.1.md +61 -0
- data/man/ronin-db-hosts.1 +86 -0
- data/man/ronin-db-hosts.1.md +64 -0
- data/man/ronin-db-ips.1 +90 -0
- data/man/ronin-db-ips.1.md +67 -0
- data/man/ronin-db-irb.1 +61 -0
- data/man/ronin-db-irb.1.md +46 -0
- data/man/ronin-db-list.1 +58 -0
- data/man/ronin-db-list.1.md +44 -0
- data/man/ronin-db-migrate.1 +44 -0
- data/man/ronin-db-migrate.1.md +32 -0
- data/man/ronin-db-remove.1 +55 -0
- data/man/ronin-db-remove.1.md +42 -0
- data/man/ronin-db-urls.1 +98 -0
- data/man/ronin-db-urls.1.md +73 -0
- data/ronin-db.gemspec +78 -0
- data/spec/cli/commands/add_spec.rb +220 -0
- data/spec/cli/commands/edit_spec.rb +12 -0
- data/spec/cli/commands/irb_spec.rb +26 -0
- data/spec/cli/database_command_spec.rb +53 -0
- data/spec/cli/model_command_spec.rb +237 -0
- data/spec/cli/ruby_shell_spec.rb +14 -0
- data/spec/cli/uri_methods_spec.rb +190 -0
- data/spec/spec_helper.rb +15 -0
- metadata +200 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db - A common database library for managing and querying security data.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db 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 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. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/cli/model_command'
|
22
|
+
require 'ronin/db/cli/modifiable'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module DB
|
26
|
+
class CLI
|
27
|
+
module Commands
|
28
|
+
#
|
29
|
+
# Manages all URLs in the database.
|
30
|
+
#
|
31
|
+
# ## Usage
|
32
|
+
#
|
33
|
+
# ronin-db urls [options]
|
34
|
+
#
|
35
|
+
# ## Options
|
36
|
+
#
|
37
|
+
# --db NAME The database to connect to (Default: default)
|
38
|
+
# --db-uri URI The database URI to connect to
|
39
|
+
# -v, --verbose Enables verbose output
|
40
|
+
# --add VALUE Adds a value to the database
|
41
|
+
# --import FILE Imports the values from the FILE into the database
|
42
|
+
# --delete VALUE Deletes a value from the database
|
43
|
+
# --delete-all Deletes all values from the database
|
44
|
+
# --http
|
45
|
+
# --https
|
46
|
+
# -H, --host HOST
|
47
|
+
# -P, --port PORT
|
48
|
+
# -d, --directory SUBDIR
|
49
|
+
# -E, --ext EXT
|
50
|
+
# -q NAME
|
51
|
+
# --with-query-param
|
52
|
+
# -Q VALUE
|
53
|
+
# --with-query-value
|
54
|
+
#
|
55
|
+
class Urls < ModelCommand
|
56
|
+
|
57
|
+
include Modifiable
|
58
|
+
|
59
|
+
model_file 'ronin/db/url'
|
60
|
+
model_name 'URL'
|
61
|
+
|
62
|
+
option :http, desc: 'Searches for http:// URLs' do
|
63
|
+
@query_method_calls << :http
|
64
|
+
end
|
65
|
+
|
66
|
+
option :https, desc: 'Searches for https:// URLs' do
|
67
|
+
@query_method_calls << :https
|
68
|
+
end
|
69
|
+
|
70
|
+
option :host, short: '-H',
|
71
|
+
value: {
|
72
|
+
type: String,
|
73
|
+
usage: 'HOST'
|
74
|
+
},
|
75
|
+
desc: 'Searches for the associated HOST(s)' do |host|
|
76
|
+
@query_method_calls << [:with_host_name, [host]]
|
77
|
+
end
|
78
|
+
|
79
|
+
option :port, short: '-p',
|
80
|
+
value: {
|
81
|
+
type: Integer,
|
82
|
+
usage: 'PORT'
|
83
|
+
},
|
84
|
+
desc: 'Searches for the associated PORT(s)' do |port|
|
85
|
+
@query_method_calls << [:with_port_number, [port]]
|
86
|
+
end
|
87
|
+
|
88
|
+
option :path, value: {
|
89
|
+
type: String,
|
90
|
+
usage: 'PATH'
|
91
|
+
},
|
92
|
+
desc: 'Searches for all URLs with the PATH' do |path|
|
93
|
+
@query_method_calls << [:where, [], {path: path}]
|
94
|
+
end
|
95
|
+
|
96
|
+
option :fragment, value: {
|
97
|
+
type: String,
|
98
|
+
usage: 'FRAGMENT'
|
99
|
+
},
|
100
|
+
desc: 'Searches for all URLs with the FRAGMENT' do |fragment|
|
101
|
+
@query_method_calls << [:where, [], {fragment: fragment}]
|
102
|
+
end
|
103
|
+
|
104
|
+
option :directory, short: '-d',
|
105
|
+
value: {
|
106
|
+
type: String,
|
107
|
+
usage: 'DIR'
|
108
|
+
},
|
109
|
+
desc: 'Searches for the associated DIR' do |dir|
|
110
|
+
@query_method_calls << [:with_directory, [dir]]
|
111
|
+
end
|
112
|
+
|
113
|
+
option :with_ext, short: '-E',
|
114
|
+
value: {
|
115
|
+
type: String,
|
116
|
+
usage: 'EXT'
|
117
|
+
},
|
118
|
+
desc: 'Searches for URLs with the file extension' do |ext|
|
119
|
+
@query_method_calls << [:with_ext, [ext]]
|
120
|
+
end
|
121
|
+
|
122
|
+
option :query_string, short: '-q',
|
123
|
+
value: {
|
124
|
+
type: String,
|
125
|
+
usage: 'STRING',
|
126
|
+
},
|
127
|
+
desc: 'Searches for all URLs with the query string' do |string|
|
128
|
+
@query_method_calls << [:where, [], {query: string}]
|
129
|
+
end
|
130
|
+
|
131
|
+
option :with_query_param, short: '-P',
|
132
|
+
value: {
|
133
|
+
type: String,
|
134
|
+
usage: 'NAME[=VALUE]'
|
135
|
+
},
|
136
|
+
desc: 'Searches for the associated query-param NAME(s)' do |string|
|
137
|
+
name, value = string.split('=',2)
|
138
|
+
|
139
|
+
if value
|
140
|
+
@query_method_calls << [:with_query_param, [name, value]]
|
141
|
+
else
|
142
|
+
@query_method_calls << [:with_query_param_name, [name]]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
option :with_query_param_name, value: {
|
147
|
+
type: String,
|
148
|
+
usage: 'NAME'
|
149
|
+
},
|
150
|
+
desc: 'Searches for the associated query-param VALUE(s)' do |name|
|
151
|
+
@query_method_calls << [:with_query_param_name, [name]]
|
152
|
+
end
|
153
|
+
|
154
|
+
option :with_query_param_value, value: {
|
155
|
+
type: String,
|
156
|
+
usage: 'VALUE'
|
157
|
+
},
|
158
|
+
desc: 'Searches for the associated query-param VALUE(s)' do |value|
|
159
|
+
@query_method_calls << [:with_query_param_value, [value]]
|
160
|
+
end
|
161
|
+
|
162
|
+
description 'Manages URLs'
|
163
|
+
|
164
|
+
man_page 'ronin-db-urls.1'
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db - A common database library for managing and querying security data.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db 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 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. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/cli/command'
|
22
|
+
require 'ronin/db/cli/uri_methods'
|
23
|
+
require 'ronin/db'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module DB
|
27
|
+
class CLI
|
28
|
+
#
|
29
|
+
# Base class for all commands that access the database.
|
30
|
+
#
|
31
|
+
class DatabaseCommand < Command
|
32
|
+
|
33
|
+
include URIMethods
|
34
|
+
|
35
|
+
option :db, value: {
|
36
|
+
type: DB.config.keys,
|
37
|
+
default: :default,
|
38
|
+
usage: 'NAME'
|
39
|
+
},
|
40
|
+
desc: 'The database to connect to'
|
41
|
+
|
42
|
+
option :db_uri, value: {
|
43
|
+
type: String,
|
44
|
+
usage: 'URI'
|
45
|
+
},
|
46
|
+
desc: 'The database URI to connect to'
|
47
|
+
|
48
|
+
#
|
49
|
+
# The database connection configuration.
|
50
|
+
#
|
51
|
+
# @return [Hash{Symbol => String,Integer}]
|
52
|
+
#
|
53
|
+
def config
|
54
|
+
if options[:db_uri]
|
55
|
+
parse_uri(options[:db_uri])
|
56
|
+
else
|
57
|
+
DB.config[options[:db]]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Connects to the database.
|
63
|
+
#
|
64
|
+
def connect
|
65
|
+
DB.connect(config)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db - A common database library for managing and querying security data.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db 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 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. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/cli/database_command'
|
22
|
+
require 'ronin/core/cli/logging'
|
23
|
+
|
24
|
+
require 'command_kit/options/verbose'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
class CLI
|
29
|
+
#
|
30
|
+
# A base-command for database models commands.
|
31
|
+
#
|
32
|
+
class ModelCommand < DatabaseCommand
|
33
|
+
|
34
|
+
include CommandKit::Options::Verbose
|
35
|
+
include Core::CLI::Logging
|
36
|
+
|
37
|
+
#
|
38
|
+
# Sets or gets the model file to require.
|
39
|
+
#
|
40
|
+
# @param [String, nil] new_model_file
|
41
|
+
# The new model file.
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
# The model file to require.
|
45
|
+
#
|
46
|
+
# @raise [NotImplementedError]
|
47
|
+
# The class did not define a `model_file`.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# model_file 'ronin/db/foo'
|
51
|
+
#
|
52
|
+
def self.model_file(new_model_file=nil)
|
53
|
+
if new_model_file
|
54
|
+
@model_file = new_model_file
|
55
|
+
else
|
56
|
+
@model_file ||= if superclass < ModelCommand
|
57
|
+
superclass.model_file
|
58
|
+
else
|
59
|
+
raise(NotImplementedError,"#{self} did not define model_file")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Sets or gets the model name to lookup.
|
66
|
+
#
|
67
|
+
# @param [String, nil] new_model_name
|
68
|
+
# The new model name.
|
69
|
+
#
|
70
|
+
# @return [String]
|
71
|
+
# The model name to lookup.
|
72
|
+
#
|
73
|
+
# @raise [NotImplementedError]
|
74
|
+
# The class did not define a `model_name`.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# model_name 'Foo'
|
78
|
+
#
|
79
|
+
def self.model_name(new_model_name=nil)
|
80
|
+
if new_model_name
|
81
|
+
@model_name = new_model_name
|
82
|
+
else
|
83
|
+
@model_name ||= if superclass < ModelCommand
|
84
|
+
superclass.model_name
|
85
|
+
else
|
86
|
+
raise(NotImplementedError,"#{self} did not define model_name")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# The query method calls to chain together.
|
92
|
+
#
|
93
|
+
# @return [Array<(Symbol),
|
94
|
+
# (Symbol, Array),
|
95
|
+
# (Symbol, Hash),
|
96
|
+
# (Symbol, Array, Hash)>]
|
97
|
+
attr_reader :query_method_calls
|
98
|
+
|
99
|
+
#
|
100
|
+
# Initializes the command.
|
101
|
+
#
|
102
|
+
# @param [Hash{Symbol => Object}] kwargs
|
103
|
+
# Additional keyword arguments.
|
104
|
+
#
|
105
|
+
def initialize(**kwargs)
|
106
|
+
super(**kwargs)
|
107
|
+
|
108
|
+
@query_method_calls = []
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Runs the command.
|
113
|
+
#
|
114
|
+
def run
|
115
|
+
connect
|
116
|
+
list
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Connects to the database.
|
121
|
+
#
|
122
|
+
def connect
|
123
|
+
# connect to the database but do not load other models.
|
124
|
+
DB.connect(config, load_models: false)
|
125
|
+
|
126
|
+
# load and connect the model
|
127
|
+
model.connection
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# The model to query.
|
132
|
+
#
|
133
|
+
# @return [Class<ActiveRecord::Base>]
|
134
|
+
# The loaded model.
|
135
|
+
#
|
136
|
+
# @raise [LoadError]
|
137
|
+
# The {model_file} could not be loaded.
|
138
|
+
#
|
139
|
+
# @raise [NameError]
|
140
|
+
# The {model_name} was not found within {Ronin::DB}.
|
141
|
+
#
|
142
|
+
def load_model
|
143
|
+
require self.class.model_file
|
144
|
+
|
145
|
+
Ronin::DB.const_get(self.class.model_name)
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# The model to query.
|
150
|
+
#
|
151
|
+
# @return [Class<ActiveRecord::Base>]
|
152
|
+
# The loaded model.
|
153
|
+
#
|
154
|
+
def model
|
155
|
+
@model ||= load_model
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# Queries and lists records.
|
160
|
+
#
|
161
|
+
def list
|
162
|
+
records = query
|
163
|
+
records.each(&method(:print_record))
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Builds a new query by chaining together the method calls defined by
|
168
|
+
# {#query_method_calls}.
|
169
|
+
#
|
170
|
+
# @return [ActiveRecord::Relation, ActiveRecord::QueryMethods::WhereChain]
|
171
|
+
# The new query.
|
172
|
+
#
|
173
|
+
def query
|
174
|
+
common_object_methods = Object.public_instance_methods
|
175
|
+
|
176
|
+
query = model.all
|
177
|
+
|
178
|
+
@query_method_calls.each do |method,arguments,kwargs={}|
|
179
|
+
if common_object_methods.include?(method)
|
180
|
+
raise(ArgumentError,"cannot call method Object##{method} on query #{query.inspect}")
|
181
|
+
end
|
182
|
+
|
183
|
+
query = query.public_send(method,*arguments,**kwargs)
|
184
|
+
end
|
185
|
+
|
186
|
+
return query
|
187
|
+
end
|
188
|
+
|
189
|
+
#
|
190
|
+
# Prints the given record.
|
191
|
+
#
|
192
|
+
# @param [ActiveRecord::Base] record
|
193
|
+
# The record to print.
|
194
|
+
#
|
195
|
+
def print_record(record)
|
196
|
+
puts record
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db - A common database library for managing and querying security data.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db 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 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. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
module Ronin
|
22
|
+
module DB
|
23
|
+
class CLI
|
24
|
+
#
|
25
|
+
# Allows a {ModelCommand} to add, import, delete, or delete all records.
|
26
|
+
#
|
27
|
+
module Modifiable
|
28
|
+
#
|
29
|
+
# Adds the `--add`, `--import`, `--delete`, and `--delete-all` options
|
30
|
+
# to the command.
|
31
|
+
#
|
32
|
+
# @param [Class<ModelCommand>] command
|
33
|
+
# The command class including {Modifiable}.
|
34
|
+
#
|
35
|
+
def self.included(command)
|
36
|
+
command.option :add, value: {
|
37
|
+
type: String,
|
38
|
+
usage: 'VALUE'
|
39
|
+
},
|
40
|
+
desc: 'Adds a value to the database'
|
41
|
+
|
42
|
+
command.option :import, value: {
|
43
|
+
type: String,
|
44
|
+
usage: 'FILE'
|
45
|
+
},
|
46
|
+
desc: 'Imports the values from the FILE into the database'
|
47
|
+
|
48
|
+
command.option :delete, value: {
|
49
|
+
type: String,
|
50
|
+
usage: 'VALUE'
|
51
|
+
},
|
52
|
+
desc: 'Deletes a value from the database'
|
53
|
+
|
54
|
+
command.option :delete_all, desc: 'Deletes all values from the database'
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Runs the command.
|
59
|
+
#
|
60
|
+
def run
|
61
|
+
connect
|
62
|
+
|
63
|
+
if options[:add]
|
64
|
+
add(options[:add])
|
65
|
+
elsif options[:import]
|
66
|
+
import_file(options[:import])
|
67
|
+
elsif options[:delete]
|
68
|
+
delete(options[:delete])
|
69
|
+
elsif options[:delete_all]
|
70
|
+
delete_all
|
71
|
+
else
|
72
|
+
list
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Adds a value to the database.
|
78
|
+
#
|
79
|
+
# @param [String] value
|
80
|
+
# The value to add.
|
81
|
+
#
|
82
|
+
def add(value)
|
83
|
+
record = model.import(value)
|
84
|
+
|
85
|
+
unless record.valid?
|
86
|
+
print_error "failed to import #{value}!"
|
87
|
+
|
88
|
+
record.errors.full_messages.each do |message|
|
89
|
+
print_error " - #{message}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Imports the values from the givne file.
|
96
|
+
#
|
97
|
+
# @param [String] path
|
98
|
+
# The path to the file.
|
99
|
+
#
|
100
|
+
def import_file(path)
|
101
|
+
unless File.file?(path)
|
102
|
+
print_error "no such file or directory: #{path}"
|
103
|
+
exit(-1)
|
104
|
+
end
|
105
|
+
|
106
|
+
File.open(path) do |file|
|
107
|
+
model.transaction do
|
108
|
+
file.each_line(chomp: true) do |value|
|
109
|
+
log_info "Importing #{value} ..." if verbose?
|
110
|
+
|
111
|
+
add(value)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Deletes a value from the database.
|
119
|
+
#
|
120
|
+
# @param [String] value
|
121
|
+
# The value to lookup and delete.
|
122
|
+
#
|
123
|
+
def delete(value)
|
124
|
+
if (record = model.lookup(value))
|
125
|
+
record.destroy
|
126
|
+
else
|
127
|
+
print_error "value does not exist in the database: #{value}"
|
128
|
+
exit(-1)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Deletes all values from the database.
|
134
|
+
#
|
135
|
+
def delete_all
|
136
|
+
model.destroy_all
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db - A common database library for managing and querying security data.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db 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 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. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/ui/cli/model_command'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
|
24
|
+
require 'dm-serializer'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
module CLI
|
29
|
+
#
|
30
|
+
# A base-command class for listing Database Resources.
|
31
|
+
#
|
32
|
+
class ResourcesCommand < ModelCommand
|
33
|
+
|
34
|
+
option :csv, type: true,
|
35
|
+
description: 'CSV output'
|
36
|
+
|
37
|
+
option :xml, type: true,
|
38
|
+
description: 'XML output'
|
39
|
+
|
40
|
+
option :yaml, type: true,
|
41
|
+
description: 'YAML output'
|
42
|
+
|
43
|
+
option :json, type: true,
|
44
|
+
description: 'JSON output'
|
45
|
+
|
46
|
+
#
|
47
|
+
# Default method performs the query and prints the found resources.
|
48
|
+
#
|
49
|
+
# @since 1.1.0
|
50
|
+
#
|
51
|
+
# @api semipublic
|
52
|
+
#
|
53
|
+
def execute
|
54
|
+
if @import
|
55
|
+
self.class.model.import(@import) do |resource|
|
56
|
+
print_info "Imported #{resource}"
|
57
|
+
end
|
58
|
+
else
|
59
|
+
print_resources(query)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
|
65
|
+
#
|
66
|
+
# Sets the model used by the command.
|
67
|
+
#
|
68
|
+
# @see ModelCommand.model
|
69
|
+
#
|
70
|
+
# @since 1.3.0
|
71
|
+
#
|
72
|
+
def self.model(model=nil)
|
73
|
+
if (model && model < Model::Importable)
|
74
|
+
option :import, type: String,
|
75
|
+
flag: '-i',
|
76
|
+
usage: 'FILE',
|
77
|
+
description: 'The file to import'
|
78
|
+
end
|
79
|
+
|
80
|
+
return super(model)
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Default method which will print every queried resource.
|
85
|
+
#
|
86
|
+
# @param [DataMapper::Resource] resource
|
87
|
+
# A queried resource from the Database.
|
88
|
+
#
|
89
|
+
# @since 1.1.0
|
90
|
+
#
|
91
|
+
# @api semipublic
|
92
|
+
#
|
93
|
+
def print_resource(resource)
|
94
|
+
puts resource
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Prints multiple resources.
|
99
|
+
#
|
100
|
+
# @param [DataMapper::Collection] resources
|
101
|
+
# The query to print.
|
102
|
+
#
|
103
|
+
# @since 1.1.0
|
104
|
+
#
|
105
|
+
# @api semipublic
|
106
|
+
#
|
107
|
+
def print_resources(resources)
|
108
|
+
if csv? then puts resources.to_csv
|
109
|
+
elsif xml? then puts resources.to_xml
|
110
|
+
elsif yaml? then puts resources.to_yaml
|
111
|
+
elsif json? then puts resources.to_json
|
112
|
+
else
|
113
|
+
resources.each { |resource| print_resource(resource) }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|