console1984 0.1.16 → 0.1.20

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 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
  - - ">="