console1984 0.1.16 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22d6415f6dbc30049954458c38027c5a33737429d93141bfdaeb3c9d654ff3a3
4
- data.tar.gz: 151005da988be49ed8e46c6f73beeea4b2bc2a137d70d6d6296bd87ca4a54256
3
+ metadata.gz: f982f92b4547b0618ba7c124fde7ac1c26acc0618f77be753171fcff54e54043
4
+ data.tar.gz: 828b81e3719f909263a3e3ccc08a937ece36c6c4d2ea976ef7412413e6797be6
5
5
  SHA512:
6
- metadata.gz: 3ae3c452e1cb58b863ee16f2e90a411419c8fbdb366c1c881801499846861e9a5e5d558eb08091c801b26907dbc92ffdc9f994e2a074e84e39ca98e6c6a7c0bf
7
- data.tar.gz: 61fac61bac50294544c6035fa981d43fd4fc9818475d1c1132d38f09684c1e94a7bf6ac763e8295acfa12398e212508c8144a3f32ce158e4d3c606362d2cff83
6
+ metadata.gz: a832cb53bee3f1edd70bd5f4c469048108f4bc8cc39ef3aa452319ca1a157f145212476bc69b3ee5a215b686ed0e6f9945fb1ad497c1493a65a1531cd542b1b2
7
+ data.tar.gz: f6e684bf6fa011a5ba72de4a40919ffc8dc86e1d4bdcea4df2d977d85918b1871d270e2d770e9e1aae3c09dfab9af9c0f59ba4ef7d6cf6bf645851bf5881db3d
data/README.md CHANGED
@@ -35,6 +35,9 @@ By default, console1984 is only enabled in `production`. You can configure the t
35
35
  config.console1984.protected_environments = %i[ production staging ]
36
36
  ```
37
37
 
38
+ Finally, you need to [configure Active Record Encryption](https://edgeguides.rubyonrails.org/active_record_encryption.html#setup) in your
39
+ project. This is because the library stores the tracked console commands encrypted.
40
+
38
41
  ## How it works
39
42
 
40
43
  ### Session activity logging
@@ -153,6 +156,27 @@ These config options are namespaced in `config.console1984`:
153
156
  | `incinerate_after` | The period to keep sessions around before incinerate them. Default `30.days`. |
154
157
  | `incineration_queue` | The name of the queue for session incineration jobs. Default `console1984_incineration`. |
155
158
 
159
+ ### SSH Config
160
+
161
+ To automatically set the `CONSOLE_USER` env var for sessions, you'll need to configure SSH on the server to accept the environment variable.
162
+
163
+ On the server, edit `/etc/ssh/sshd_config` to accept the environment variable:
164
+ ```
165
+ AcceptEnv LANG LC_* CONSOLE_USER
166
+ ```
167
+
168
+ Restart the SSH server to use the new config:
169
+ ```bash
170
+ service sshd restart
171
+ ```
172
+
173
+ On the client side, you can provide this env var from your clients by adding the variable to the ssh config:
174
+
175
+ ```
176
+ Host *
177
+ SetEnv CONSOLE_USER=david
178
+ ```
179
+
156
180
  ## About built-in protection mechanisms
157
181
 
158
182
  `console1984` adds many protection mechanisms to prevent tampering. This includes attempts to alter data in auditing tables or monkey patching certain classes to change how the system works. If you find a way to circumvent these tampering controls, please [report an issue](https://github.com/basecamp/console1984/issues).
@@ -25,6 +25,6 @@ module Console1984::Session::Incineratable
25
25
  end
26
26
 
27
27
  def earliest_possible_incineration_date
28
- created_at + Console1984.incinerate_after
28
+ created_at + Console1984.incinerate_after - 1.second
29
29
  end
30
30
  end
@@ -10,6 +10,7 @@ class Console1984::CommandExecutor
10
10
  include Console1984::Freezeable
11
11
 
12
12
  delegate :username_resolver, :session_logger, :shield, to: Console1984
13
+ attr_reader :last_suspicious_command_error
13
14
 
14
15
  # Logs and validates +commands+, and executes the passed block in a protected environment.
15
16
  #
@@ -19,14 +20,14 @@ class Console1984::CommandExecutor
19
20
  run_as_system { session_logger.before_executing commands }
20
21
  validate_command commands
21
22
  execute_in_protected_mode(&block)
22
- rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError
23
- flag_suspicious(commands)
24
- rescue Console1984::Errors::SuspiciousCommandAttempted
25
- flag_suspicious(commands)
23
+ rescue Console1984::Errors::ForbiddenCommandAttempted, FrozenError => error
24
+ flag_suspicious(commands, error: error)
25
+ rescue Console1984::Errors::SuspiciousCommandAttempted => error
26
+ flag_suspicious(commands, error: error)
26
27
  execute_in_protected_mode(&block)
27
- rescue Console1984::Errors::ForbiddenCommandExecuted
28
+ rescue Console1984::Errors::ForbiddenCommandExecuted => error
28
29
  # We detected that a forbidden command was executed. We exit IRB right away.
29
- flag_suspicious(commands)
30
+ flag_suspicious(commands, error: error)
30
31
  Console1984.supervisor.exit_irb
31
32
  ensure
32
33
  run_as_system { session_logger.after_executing commands }
@@ -70,11 +71,7 @@ class Console1984::CommandExecutor
70
71
  end
71
72
 
72
73
  def from_irb?(backtrace)
73
- executing_user_command? && backtrace.find do |line|
74
- line_from_irb = line =~ /^[^\/]/
75
- break if !(line =~ /console1984\/lib/ || line_from_irb)
76
- line_from_irb
77
- end
74
+ executing_user_command? && backtrace.first.to_s =~ /^[^\/]/
78
75
  end
79
76
 
80
77
  private
@@ -86,9 +83,10 @@ class Console1984::CommandExecutor
86
83
  Console1984::CommandValidator.from_config(Console1984.protections_config.validations)
87
84
  end
88
85
 
89
- def flag_suspicious(commands)
86
+ def flag_suspicious(commands, error: nil)
90
87
  puts "Forbidden command attempted: #{commands.join("\n")}"
91
88
  run_as_system { session_logger.suspicious_commands_attempted commands }
89
+ @last_suspicious_command_error = error
92
90
  nil
93
91
  end
94
92
 
@@ -5,7 +5,7 @@ module Console1984::Ext::ActiveRecord::ProtectedAuditableTables
5
5
  %i[ execute exec_query exec_insert exec_delete exec_update exec_insert_all ].each do |method|
6
6
  define_method method do |*args, **kwargs|
7
7
  sql = args.first
8
- if Console1984.command_executor.executing_user_command? && sql =~ auditable_tables_regexp
8
+ if Console1984.command_executor.executing_user_command? && sql.b =~ auditable_tables_regexp
9
9
  raise Console1984::Errors::ForbiddenCommandAttempted, "#{sql}"
10
10
  else
11
11
  super(*args, **kwargs)
@@ -16,7 +16,7 @@ module Console1984::Ext::Core::Object
16
16
 
17
17
  class_methods do
18
18
  def const_get(*arguments)
19
- if Console1984.command_executor.executing_user_command?
19
+ if Console1984.command_executor.from_irb?(caller)
20
20
  begin
21
21
  # To validate if it's an invalid constant, we try to declare a class with it.
22
22
  # We essentially leverage Console1984::CommandValidator::ForbiddenReopeningValidation here:
@@ -0,0 +1,24 @@
1
+ # Prevents loading forbidden classes dynamically.
2
+ #
3
+ # See extension to +Console1984::Ext::Core::Object#const_get+.
4
+ module Console1984::Ext::Core::String
5
+ extend ActiveSupport::Concern
6
+
7
+ include Console1984::Freezeable
8
+ self.prevent_instance_data_manipulation_after_freezing = false
9
+
10
+ def constantize
11
+ if Console1984.command_executor.from_irb?(caller)
12
+ begin
13
+ Console1984.command_executor.validate_command("class #{self}; end")
14
+ super
15
+ rescue Console1984::Errors::ForbiddenCommandAttempted
16
+ raise
17
+ rescue StandardError
18
+ super
19
+ end
20
+ else
21
+ super
22
+ end
23
+ end
24
+ end
@@ -13,4 +13,13 @@ module Console1984::Ext::Irb::Commands
13
13
  def encrypt!
14
14
  shield.enable_protected_mode
15
15
  end
16
+
17
+ # This returns the last error that prevented a command execution in the console
18
+ # or nil if there isn't any.
19
+ #
20
+ # This is meant for internal usage when debugging legit commands that are wrongly
21
+ # prevented.
22
+ def _console_last_suspicious_command_error
23
+ Console1984.command_executor.last_suspicious_command_error
24
+ end
16
25
  end
@@ -2,13 +2,13 @@
2
2
  module Console1984::Ext::Socket::TcpSocket
3
3
  include Console1984::Freezeable
4
4
 
5
- def write(*args)
5
+ def write(...)
6
6
  protecting do
7
7
  super
8
8
  end
9
9
  end
10
10
 
11
- def write_nonblock(*args)
11
+ def write_nonblock(...)
12
12
  protecting do
13
13
  super
14
14
  end
@@ -6,6 +6,11 @@ class Console1984::Shield::Modes::Protected
6
6
 
7
7
  thread_mattr_accessor :currently_protected_urls, default: []
8
8
 
9
+ # Materialize the thread attribute before freezing the class. +thread_mattr_accessor+ attributes rely on
10
+ # setting a class variable the first time they are referenced, and that will fail in frozen classes
11
+ # like this one.
12
+ currently_protected_urls
13
+
9
14
  def execute(&block)
10
15
  protecting(&block)
11
16
  end
@@ -40,6 +40,7 @@ class Console1984::Shield
40
40
  def extend_core_ruby
41
41
  Object.prepend Console1984::Ext::Core::Object
42
42
  Module.prepend Console1984::Ext::Core::Module
43
+ String.prepend Console1984::Ext::Core::String
43
44
  end
44
45
 
45
46
  def extend_sockets
@@ -63,7 +64,6 @@ class Console1984::Shield
63
64
  if Object.const_defined?(class_string)
64
65
  klass = class_string.constantize
65
66
  klass.prepend(Console1984::Ext::ActiveRecord::ProtectedAuditableTables)
66
- klass.include(Console1984::Freezeable)
67
67
  end
68
68
  end
69
69
  end
@@ -1,3 +1,3 @@
1
1
  module Console1984
2
- VERSION = '0.1.16'
2
+ VERSION = '0.1.20'
3
3
  end
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.16
4
+ version: 0.1.20
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-09-24 00:00:00.000000000 Z
11
+ date: 2021-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -225,6 +225,7 @@ files:
225
225
  - lib/console1984/ext/active_record/protected_auditable_tables.rb
226
226
  - lib/console1984/ext/core/module.rb
227
227
  - lib/console1984/ext/core/object.rb
228
+ - lib/console1984/ext/core/string.rb
228
229
  - lib/console1984/ext/irb/commands.rb
229
230
  - lib/console1984/ext/irb/context.rb
230
231
  - lib/console1984/ext/socket/tcp_socket.rb
@@ -260,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
260
261
  requirements:
261
262
  - - ">="
262
263
  - !ruby/object:Gem::Version
263
- version: '0'
264
+ version: 2.7.0
264
265
  required_rubygems_version: !ruby/object:Gem::Requirement
265
266
  requirements:
266
267
  - - ">="