console1984 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -1
- data/config/command_protections.yml +17 -0
- data/lib/console1984/command_executor.rb +94 -0
- data/lib/console1984/command_validator/forbidden_constant_reference_validation.rb +31 -0
- data/lib/console1984/command_validator/forbidden_reopening_validation.rb +29 -0
- data/lib/console1984/command_validator/parsed_command.rb +64 -0
- data/lib/console1984/command_validator/suspicious_terms_validation.rb +22 -0
- data/lib/console1984/command_validator.rb +71 -0
- data/lib/console1984/config.rb +9 -5
- data/lib/console1984/engine.rb +2 -0
- data/lib/console1984/errors.rb +10 -1
- data/lib/console1984/{protected_auditable_tables.rb → ext/active_record/protected_auditable_tables.rb} +2 -4
- data/lib/console1984/ext/core/object.rb +42 -0
- data/lib/console1984/ext/irb/commands.rb +16 -0
- data/lib/console1984/{protected_context.rb → ext/irb/context.rb} +5 -5
- data/lib/console1984/{protected_tcp_socket.rb → ext/socket/tcp_socket.rb} +3 -3
- data/lib/console1984/freezeable.rb +15 -5
- data/lib/console1984/{supervisor/input_output.rb → input_output.rb} +8 -2
- data/lib/console1984/messages.rb +0 -10
- data/lib/console1984/shield/modes/protected.rb +27 -0
- data/lib/console1984/shield/modes/unprotected.rb +8 -0
- data/lib/console1984/shield/modes.rb +60 -0
- data/lib/console1984/shield.rb +86 -0
- data/lib/console1984/supervisor.rb +24 -33
- data/lib/console1984/version.rb +1 -1
- data/lib/console1984.rb +36 -17
- metadata +61 -14
- data/config/routes.rb +0 -9
- data/lib/console1984/commands.rb +0 -16
- data/lib/console1984/protected_object.rb +0 -15
- data/lib/console1984/supervisor/accesses/protected.rb +0 -12
- data/lib/console1984/supervisor/accesses/unprotected.rb +0 -7
- data/lib/console1984/supervisor/accesses.rb +0 -41
- data/lib/console1984/supervisor/executor.rb +0 -65
- data/lib/console1984/supervisor/protector.rb +0 -55
data/lib/console1984/version.rb
CHANGED
data/lib/console1984.rb
CHANGED
@@ -4,38 +4,57 @@ require "zeitwerk"
|
|
4
4
|
class_loader = Zeitwerk::Loader.for_gem
|
5
5
|
class_loader.setup
|
6
6
|
|
7
|
+
# = Console 1984
|
8
|
+
#
|
9
|
+
# Console1984 is an IRB-based Rails console extension that does
|
10
|
+
# three things:
|
11
|
+
#
|
12
|
+
# * Record console sessions with their user, reason and commands.
|
13
|
+
# * Protect encrypted data by showing the ciphertexts when you visualize it.
|
14
|
+
# * Protect access to external systems that contain sensitive information (such as Redis
|
15
|
+
# or Elasticsearch).
|
16
|
+
#
|
17
|
+
# == Session logging
|
18
|
+
#
|
19
|
+
# The console will record the session, its user and the commands entered. The logic to
|
20
|
+
# persist sessions is handled by the configured session logger, which is
|
21
|
+
# Console1984::SessionsLogger::Database by default.
|
22
|
+
#
|
23
|
+
# == Execution of commands
|
24
|
+
#
|
25
|
+
# The console will work in two modes:
|
26
|
+
#
|
27
|
+
# * Protected: It won't show encrypted information (it will show the ciphertexts instead)
|
28
|
+
# and it won't allow connections to protected urls.
|
29
|
+
# * Unprotected: it allows access to encrypted information and protected urls. The commands
|
30
|
+
# executed in this mode as flagged as sensitive.
|
31
|
+
#
|
32
|
+
# Console1984::CommandExecutor handles the execution of commands applying the corresponding
|
33
|
+
# protection mechanisms.´
|
34
|
+
#
|
35
|
+
# == Internal tampering prevention
|
36
|
+
#
|
37
|
+
# Finally, console1984 includes protection mechanisms against internal tampering while using
|
38
|
+
# the console. For example, to prevent the user from deleting audit trails. See
|
39
|
+
# Console1984::Shield and Console1984::CommandValidator to learn more.
|
7
40
|
module Console1984
|
8
41
|
include Messages, Freezeable
|
9
42
|
|
10
43
|
mattr_accessor :supervisor, default: Supervisor.new
|
44
|
+
|
11
45
|
mattr_reader :config, default: Config.new
|
12
|
-
mattr_accessor :class_loader
|
13
46
|
|
14
|
-
|
47
|
+
mattr_accessor :class_loader
|
15
48
|
|
16
49
|
class << self
|
17
50
|
Config::PROPERTIES.each do |property|
|
18
51
|
delegate property, to: :config
|
19
52
|
end
|
20
53
|
|
54
|
+
# Returns whether the console is currently running in protected mode or not.
|
21
55
|
def running_protected_environment?
|
22
56
|
protected_environments.collect(&:to_sym).include?(Rails.env.to_sym)
|
23
57
|
end
|
24
|
-
|
25
|
-
def protecting(&block)
|
26
|
-
protecting_connections do
|
27
|
-
ActiveRecord::Encryption.protecting_encrypted_data(&block)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
def protecting_connections
|
33
|
-
old_currently_protected_urls = self.currently_protected_urls
|
34
|
-
self.currently_protected_urls = protected_urls
|
35
|
-
yield
|
36
|
-
ensure
|
37
|
-
self.currently_protected_urls = old_currently_protected_urls
|
38
|
-
end
|
39
58
|
end
|
40
59
|
end
|
41
60
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: console1984
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorge Manrubia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parser
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: benchmark-ips
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +150,34 @@ dependencies:
|
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pg
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: mysql2
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
139
181
|
description:
|
140
182
|
email:
|
141
183
|
- jorge@basecamp.com
|
@@ -153,27 +195,32 @@ files:
|
|
153
195
|
- app/models/console1984/session.rb
|
154
196
|
- app/models/console1984/session/incineratable.rb
|
155
197
|
- app/models/console1984/user.rb
|
156
|
-
- config/
|
198
|
+
- config/command_protections.yml
|
157
199
|
- db/migrate/20210517203931_create_console1984_tables.rb
|
158
200
|
- lib/console1984.rb
|
159
|
-
- lib/console1984/
|
201
|
+
- lib/console1984/command_executor.rb
|
202
|
+
- lib/console1984/command_validator.rb
|
203
|
+
- lib/console1984/command_validator/forbidden_constant_reference_validation.rb
|
204
|
+
- lib/console1984/command_validator/forbidden_reopening_validation.rb
|
205
|
+
- lib/console1984/command_validator/parsed_command.rb
|
206
|
+
- lib/console1984/command_validator/suspicious_terms_validation.rb
|
160
207
|
- lib/console1984/config.rb
|
161
208
|
- lib/console1984/engine.rb
|
162
209
|
- lib/console1984/errors.rb
|
210
|
+
- lib/console1984/ext/active_record/protected_auditable_tables.rb
|
211
|
+
- lib/console1984/ext/core/object.rb
|
212
|
+
- lib/console1984/ext/irb/commands.rb
|
213
|
+
- lib/console1984/ext/irb/context.rb
|
214
|
+
- lib/console1984/ext/socket/tcp_socket.rb
|
163
215
|
- lib/console1984/freezeable.rb
|
216
|
+
- lib/console1984/input_output.rb
|
164
217
|
- lib/console1984/messages.rb
|
165
|
-
- lib/console1984/protected_auditable_tables.rb
|
166
|
-
- lib/console1984/protected_context.rb
|
167
|
-
- lib/console1984/protected_object.rb
|
168
|
-
- lib/console1984/protected_tcp_socket.rb
|
169
218
|
- lib/console1984/sessions_logger/database.rb
|
219
|
+
- lib/console1984/shield.rb
|
220
|
+
- lib/console1984/shield/modes.rb
|
221
|
+
- lib/console1984/shield/modes/protected.rb
|
222
|
+
- lib/console1984/shield/modes/unprotected.rb
|
170
223
|
- lib/console1984/supervisor.rb
|
171
|
-
- lib/console1984/supervisor/accesses.rb
|
172
|
-
- lib/console1984/supervisor/accesses/protected.rb
|
173
|
-
- lib/console1984/supervisor/accesses/unprotected.rb
|
174
|
-
- lib/console1984/supervisor/executor.rb
|
175
|
-
- lib/console1984/supervisor/input_output.rb
|
176
|
-
- lib/console1984/supervisor/protector.rb
|
177
224
|
- lib/console1984/username/env_resolver.rb
|
178
225
|
- lib/console1984/version.rb
|
179
226
|
- test/fixtures/console1984/commands.yml
|
data/config/routes.rb
DELETED
data/lib/console1984/commands.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Console1984::Commands
|
2
|
-
include Console1984::Freezeable
|
3
|
-
|
4
|
-
def decrypt!
|
5
|
-
supervisor.enable_access_to_encrypted_content
|
6
|
-
end
|
7
|
-
|
8
|
-
def encrypt!
|
9
|
-
supervisor.disable_access_to_encrypted_content
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
def supervisor
|
14
|
-
Console1984.supervisor
|
15
|
-
end
|
16
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module Console1984::ProtectedObject
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
include Console1984::Freezeable
|
5
|
-
|
6
|
-
class_methods do
|
7
|
-
def const_get(*arguments)
|
8
|
-
if Console1984.supervisor.executing_user_command? && arguments.first.to_s =~ /Console1984|ActiveRecord/
|
9
|
-
raise Console1984::Errors::ForbiddenCommand
|
10
|
-
else
|
11
|
-
super
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
class Console1984::Supervisor::Accesses::Protected
|
2
|
-
include Console1984::Freezeable
|
3
|
-
|
4
|
-
def execute(&block)
|
5
|
-
Console1984.protecting(&block)
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
9
|
-
def null_encryptor
|
10
|
-
@null_encryptor ||= ActiveRecord::Encryption::NullEncryptor.new
|
11
|
-
end
|
12
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Console1984::Supervisor::Accesses
|
2
|
-
include Console1984::Messages, Console1984::Freezeable
|
3
|
-
|
4
|
-
PROTECTED_ACCESS = Protected.new
|
5
|
-
UNPROTECTED_ACCESS = Unprotected.new
|
6
|
-
|
7
|
-
def enable_access_to_encrypted_content(silent: false)
|
8
|
-
run_system_command do
|
9
|
-
show_warning Console1984.enter_unprotected_encryption_mode_warning if !silent && protected_mode?
|
10
|
-
justification = ask_for_value "\nBefore you can access personal information, you need to ask for and get explicit consent from the user(s). #{current_username}, where can we find this consent (a URL would be great)?"
|
11
|
-
session_logger.start_sensitive_access justification
|
12
|
-
nil
|
13
|
-
end
|
14
|
-
ensure
|
15
|
-
@access = UNPROTECTED_ACCESS
|
16
|
-
nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def disable_access_to_encrypted_content(silent: false)
|
20
|
-
run_system_command do
|
21
|
-
show_warning Console1984.enter_protected_mode_warning if !silent && unprotected_mode?
|
22
|
-
session_logger.end_sensitive_access
|
23
|
-
nil
|
24
|
-
end
|
25
|
-
ensure
|
26
|
-
@access = PROTECTED_ACCESS
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
|
30
|
-
def with_encryption_mode(&block)
|
31
|
-
@access.execute(&block)
|
32
|
-
end
|
33
|
-
|
34
|
-
def unprotected_mode?
|
35
|
-
@access.is_a?(Unprotected)
|
36
|
-
end
|
37
|
-
|
38
|
-
def protected_mode?
|
39
|
-
!unprotected_mode?
|
40
|
-
end
|
41
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Console1984::Supervisor::Executor
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
include Console1984::Freezeable
|
5
|
-
|
6
|
-
def execute_supervised(commands, &block)
|
7
|
-
run_system_command { session_logger.before_executing commands }
|
8
|
-
validate_commands(commands)
|
9
|
-
execute(&block)
|
10
|
-
rescue Console1984::Errors::ForbiddenCommand, Console1984::Errors::ForbiddenCodeManipulation, FrozenError
|
11
|
-
flag_forbidden(commands)
|
12
|
-
rescue FrozenError
|
13
|
-
flag_forbidden(commands)
|
14
|
-
ensure
|
15
|
-
run_system_command { session_logger.after_executing commands }
|
16
|
-
end
|
17
|
-
|
18
|
-
def execute(&block)
|
19
|
-
run_user_command do
|
20
|
-
with_encryption_mode(&block)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def executing_user_command?
|
25
|
-
@executing_user_command
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def flag_forbidden(commands)
|
30
|
-
puts "Forbidden command attempted: #{commands.join("\n")}"
|
31
|
-
run_system_command { session_logger.suspicious_commands_attempted commands }
|
32
|
-
nil
|
33
|
-
end
|
34
|
-
|
35
|
-
def run_user_command(&block)
|
36
|
-
run_command true, &block
|
37
|
-
end
|
38
|
-
|
39
|
-
def run_system_command(&block)
|
40
|
-
run_command false, &block
|
41
|
-
end
|
42
|
-
|
43
|
-
def validate_commands(commands)
|
44
|
-
if Array(commands).find { |command| forbidden_command?(command) }
|
45
|
-
raise Console1984::Errors::ForbiddenCommand
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def forbidden_command?(command)
|
50
|
-
# This is a first protection layer. Very simple for now. We'll likely make this
|
51
|
-
# more sophisticated and configurable in future versions.
|
52
|
-
#
|
53
|
-
# We can't use our +Freezable+ concern in ActiveRecord since it relies on code
|
54
|
-
# generation on the fly.
|
55
|
-
command =~ /Console1984|console_1984|(class|module)\s+ActiveRecord::/
|
56
|
-
end
|
57
|
-
|
58
|
-
def run_command(run_by_user, &block)
|
59
|
-
original_value = @executing_user_command
|
60
|
-
@executing_user_command = run_by_user
|
61
|
-
block.call
|
62
|
-
ensure
|
63
|
-
@executing_user_command = original_value
|
64
|
-
end
|
65
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
module Console1984::Supervisor::Protector
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
include Console1984::Freezeable
|
5
|
-
|
6
|
-
private
|
7
|
-
def extend_protected_systems
|
8
|
-
extend_object
|
9
|
-
extend_irb
|
10
|
-
extend_active_record
|
11
|
-
extend_socket_classes
|
12
|
-
end
|
13
|
-
|
14
|
-
def extend_object
|
15
|
-
Object.prepend Console1984::ProtectedObject
|
16
|
-
end
|
17
|
-
|
18
|
-
def extend_irb
|
19
|
-
IRB::Context.prepend(Console1984::ProtectedContext)
|
20
|
-
Rails::ConsoleMethods.include(Console1984::Commands)
|
21
|
-
end
|
22
|
-
|
23
|
-
ACTIVE_RECORD_CONNECTION_ADAPTERS = %w[ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::PostgreSQLAdapter ActiveRecord::ConnectionAdapters::SQLite3Adapter]
|
24
|
-
|
25
|
-
def extend_active_record
|
26
|
-
ACTIVE_RECORD_CONNECTION_ADAPTERS.each do |class_string|
|
27
|
-
if Object.const_defined?(class_string)
|
28
|
-
klass = class_string.constantize
|
29
|
-
klass.prepend(Console1984::ProtectedAuditableTables)
|
30
|
-
klass.include(Console1984::Freezeable)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def extend_socket_classes
|
36
|
-
socket_classes = [TCPSocket, OpenSSL::SSL::SSLSocket]
|
37
|
-
OpenSSL::SSL::SSLSocket.include(SSLSocketRemoteAddress)
|
38
|
-
|
39
|
-
if defined?(Redis::Connection)
|
40
|
-
socket_classes.push(*[Redis::Connection::TCPSocket, Redis::Connection::SSLSocket])
|
41
|
-
end
|
42
|
-
|
43
|
-
socket_classes.compact.each do |socket_klass|
|
44
|
-
socket_klass.prepend Console1984::ProtectedTcpSocket
|
45
|
-
socket_klass.freeze
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
module SSLSocketRemoteAddress
|
50
|
-
# Make it serve remote address as TCPSocket so that our extension works for it
|
51
|
-
def remote_address
|
52
|
-
Addrinfo.getaddrinfo(hostname, 443).first
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|