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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 498f37bd3803f7f76e073d91f51e2dc69fc8a00fc575392c3869b2ae4d65d9bf
|
4
|
+
data.tar.gz: 1675df589a603042a54e6de8b835e4434f5a112158521379553e9875b25c9eeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa0edb371ac31cd2b87e1b8ddb833482516bed91ff3a5c85c12c10c2206ce7dbe8aba514a6a3aecc2e5d594eee527db78b270cd0789484960c7c98e55ca504aa
|
7
|
+
data.tar.gz: bc595388d7ca433c22a1ccc17a5bb28759cc0b0dd8b5267a061456ad0e17de58be0f95a129689e7fbe88915c709af82d0efd70a3f410f4b40cb0f7e767fa7cb6
|
data/README.md
CHANGED
@@ -155,4 +155,17 @@ These config options are namespaced in `config.console1984`:
|
|
155
155
|
|
156
156
|
`console1984` uses Ruby to add several protection mechanisms. However, because Ruby is highly dynamic, it's technically possible to circumvent most of these controls if you know what you are doing. We have made an effort to prevent such attempts, but if your organization needs bullet-proof protection against malicious actors using the console, you should consider additional security measures.
|
157
157
|
|
158
|
-
The current version includes protection mechanisms to avoid tampering the tables that store console sessions. A
|
158
|
+
The current version includes protection mechanisms to avoid tampering the tables that store console sessions. A bullet-proof mechanism would be using a read only connection when user commands are evaluated. Implementing such scheme is possible by writing a custom session logger and leveraging Rails' multi-database support. We would like that future versions of `console1984` supported this scheme directly as a configuration option.
|
159
|
+
|
160
|
+
## Running the test suite
|
161
|
+
|
162
|
+
The test suite runs against SQLite by default, but can be run against Postgres and MySQL too. It will run against the three in the CI server.
|
163
|
+
|
164
|
+
To run the suite in your computer, first, run `bin/setup` to create the docker containers for MySQL/PostgreSQL and create the databases. Then run:
|
165
|
+
|
166
|
+
```bash
|
167
|
+
bin/rails test # against SQLite (default)
|
168
|
+
bin/rails test TARGET_DB=mysql
|
169
|
+
bin/rails test TARGET_DB=postgres
|
170
|
+
bin/rails test TARGET_DB=sqlite
|
171
|
+
```
|
@@ -0,0 +1,17 @@
|
|
1
|
+
forbidden_reopening:
|
2
|
+
- ActiveRecord
|
3
|
+
- Console1984
|
4
|
+
- PG
|
5
|
+
- Mysql2
|
6
|
+
forbidden_constant_reference:
|
7
|
+
always:
|
8
|
+
- Console1984
|
9
|
+
protected:
|
10
|
+
- PG
|
11
|
+
- Mysql2
|
12
|
+
- ActiveRecord::ActiveRecordEncryption
|
13
|
+
suspicious_terms:
|
14
|
+
- console_1984
|
15
|
+
- Console1984
|
16
|
+
- secret
|
17
|
+
- credentials
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Supervise execution of console commands:
|
2
|
+
#
|
3
|
+
# * It will {validate commands}[rdoc-ref:Console1984::CommandValidator] before running
|
4
|
+
# them.
|
5
|
+
# * It will execute the commands in {protected mode}[rdoc-ref:Console1984::Shield#with_protected_mode]
|
6
|
+
# if needed.
|
7
|
+
# * It will log the command execution, and flag suspicious attempts and forbidden commands
|
8
|
+
# appropriately.
|
9
|
+
class Console1984::CommandExecutor
|
10
|
+
include Console1984::Freezeable
|
11
|
+
|
12
|
+
delegate :username_resolver, :session_logger, :shield, to: Console1984
|
13
|
+
|
14
|
+
# Logs and validates +commands+, and executes the passed block in a protected environment.
|
15
|
+
#
|
16
|
+
# Suspicious commands will be executed but flagged as suspicious. Forbidden commands will
|
17
|
+
# be prevented and flagged too.
|
18
|
+
def execute(commands, &block)
|
19
|
+
run_as_system { session_logger.before_executing commands }
|
20
|
+
validate_command commands
|
21
|
+
execute_in_protected_mode(&block)
|
22
|
+
rescue Console1984::Errors::ForbiddenCommand, FrozenError
|
23
|
+
flag_suspicious(commands)
|
24
|
+
rescue Console1984::Errors::SuspiciousCommand
|
25
|
+
flag_suspicious(commands)
|
26
|
+
execute_in_protected_mode(&block)
|
27
|
+
rescue FrozenError
|
28
|
+
flag_suspicious(commands)
|
29
|
+
ensure
|
30
|
+
run_as_system { session_logger.after_executing commands }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Executes the passed block in protected mode.
|
34
|
+
#
|
35
|
+
# See Console1984::Shield::Modes.
|
36
|
+
def execute_in_protected_mode(&block)
|
37
|
+
run_as_user do
|
38
|
+
shield.with_protected_mode(&block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Executes the passed block as a user.
|
43
|
+
#
|
44
|
+
# While the block is being executed, #executing_user_command? will return true.
|
45
|
+
# This method helps implementing certain protection mechanisms that should only act with
|
46
|
+
# user commands.
|
47
|
+
def run_as_user(&block)
|
48
|
+
run_command true, &block
|
49
|
+
end
|
50
|
+
|
51
|
+
# Executes the passed block as the system.
|
52
|
+
#
|
53
|
+
# While the block is being executed, #executing_user_command? will return false.
|
54
|
+
def run_as_system(&block)
|
55
|
+
run_command false, &block
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns whether the system is currently executing a user command.
|
59
|
+
def executing_user_command?
|
60
|
+
@executing_user_command
|
61
|
+
end
|
62
|
+
|
63
|
+
# Validates the command.
|
64
|
+
#
|
65
|
+
# See Console1984::CommandValidator.
|
66
|
+
def validate_command(command)
|
67
|
+
command_validator.validate(command)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
COMMAND_VALIDATOR_CONFIG_FILE_PATH = Console1984::Engine.root.join("config/command_protections.yml")
|
72
|
+
|
73
|
+
def command_validator
|
74
|
+
@command_validator ||= build_command_validator
|
75
|
+
end
|
76
|
+
|
77
|
+
def build_command_validator
|
78
|
+
Console1984::CommandValidator.from_config(YAML.safe_load(File.read(COMMAND_VALIDATOR_CONFIG_FILE_PATH)).symbolize_keys)
|
79
|
+
end
|
80
|
+
|
81
|
+
def flag_suspicious(commands)
|
82
|
+
puts "Forbidden command attempted: #{commands.join("\n")}"
|
83
|
+
run_as_system { session_logger.suspicious_commands_attempted commands }
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_command(run_by_user, &block)
|
88
|
+
original_value = @executing_user_command
|
89
|
+
@executing_user_command = run_by_user
|
90
|
+
block.call
|
91
|
+
ensure
|
92
|
+
@executing_user_command = original_value
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Validates references to a configured set of constants.
|
2
|
+
class Console1984::CommandValidator::ForbiddenConstantReferenceValidation
|
3
|
+
include Console1984::Freezeable
|
4
|
+
|
5
|
+
# +config+ will be a hash like:
|
6
|
+
#
|
7
|
+
# { always: [ Console1984 ], protected: [ PG, Mysql2 ] }
|
8
|
+
def initialize(shield = Console1984.shield, config)
|
9
|
+
# We make shield an injectable dependency for testing purposes. Everything is frozen
|
10
|
+
# for security purposes, so stubbing won't work.
|
11
|
+
@shield = shield
|
12
|
+
|
13
|
+
@forbidden_constants_names = config[:always] || []
|
14
|
+
@constant_names_forbidden_in_protected_mode = config[:protected] || []
|
15
|
+
end
|
16
|
+
|
17
|
+
# Raises a Console1984::Errors::ForbiddenCommand if a banned constant is referenced.
|
18
|
+
def validate(parsed_command)
|
19
|
+
if contains_invalid_const_reference?(parsed_command, @forbidden_constants_names) ||
|
20
|
+
(@shield.protected_mode? && contains_invalid_const_reference?(parsed_command, @constant_names_forbidden_in_protected_mode))
|
21
|
+
raise Console1984::Errors::ForbiddenCommand
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def contains_invalid_const_reference?(parsed_command, banned_constants)
|
27
|
+
parsed_command.constants.find do |constant_name|
|
28
|
+
banned_constants.find { |banned_constant| "#{constant_name}::".start_with?("#{banned_constant}::") }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Validates attempts to reopen classes and modules based on a configured set.
|
2
|
+
class Console1984::CommandValidator::ForbiddenReopeningValidation
|
3
|
+
include Console1984::Freezeable
|
4
|
+
|
5
|
+
attr_reader :banned_class_or_module_names
|
6
|
+
|
7
|
+
def initialize(banned_classes_or_modules)
|
8
|
+
@banned_class_or_module_names = banned_classes_or_modules.collect(&:to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Raises a Console1984::Errors::ForbiddenCommand if an banned class or module reopening
|
12
|
+
# is detected.
|
13
|
+
def validate(parsed_command)
|
14
|
+
if contains_invalid_class_or_module_declaration?(parsed_command)
|
15
|
+
raise Console1984::Errors::ForbiddenCommand
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def contains_invalid_class_or_module_declaration?(parsed_command)
|
21
|
+
parsed_command.declared_classes_or_modules.find { |class_or_module_name| banned?(class_or_module_name) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def banned?(class_or_module_name)
|
25
|
+
@banned_class_or_module_names.find do |banned_class_or_module_name|
|
26
|
+
"#{class_or_module_name}::".start_with?("#{banned_class_or_module_name}::")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Parses a command string and exposes different constructs to be used by validations.
|
2
|
+
#
|
3
|
+
# Internally, it uses the {parser}[https://github.com/whitequark/parser] gem to perform the parsing.
|
4
|
+
class Console1984::CommandValidator::ParsedCommand
|
5
|
+
include Console1984::Freezeable
|
6
|
+
|
7
|
+
attr_reader :raw_command
|
8
|
+
|
9
|
+
delegate :declared_classes_or_modules, :constants, to: :processed_ast
|
10
|
+
|
11
|
+
def initialize(raw_command)
|
12
|
+
@raw_command = Array(raw_command).join("\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def processed_ast
|
17
|
+
@processed_ast ||= CommandProcessor.new.tap do |processor|
|
18
|
+
ast = Parser::CurrentRuby.parse(raw_command)
|
19
|
+
processor.process(ast)
|
20
|
+
rescue Parser::SyntaxError
|
21
|
+
# Fail open with syntax errors
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CommandProcessor < ::Parser::AST::Processor
|
26
|
+
include AST::Processor::Mixin
|
27
|
+
include Console1984::Freezeable
|
28
|
+
|
29
|
+
attr_reader :constants, :declared_classes_or_modules
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@constants = []
|
33
|
+
@declared_classes_or_modules = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_class(node)
|
37
|
+
super
|
38
|
+
const_declaration, _, _ = *node
|
39
|
+
|
40
|
+
processor = self.class.new
|
41
|
+
processor.process(const_declaration)
|
42
|
+
@declared_classes_or_modules << processor.constants.first if processor.constants.present?
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :on_module, :on_class
|
46
|
+
|
47
|
+
def on_const(node)
|
48
|
+
super
|
49
|
+
name, const_name = *node
|
50
|
+
const_name = const_name.to_s
|
51
|
+
last_constant = @constants.last
|
52
|
+
|
53
|
+
if name.nil? || (name && name.type == :cbase) # cbase = leading ::
|
54
|
+
if last_constant&.end_with?("::")
|
55
|
+
last_constant << const_name
|
56
|
+
else
|
57
|
+
@constants << const_name
|
58
|
+
end
|
59
|
+
elsif last_constant
|
60
|
+
last_constant << "::#{const_name}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Validates that the command doesn't include a term based on a configured list.
|
2
|
+
class Console1984::CommandValidator::SuspiciousTermsValidation
|
3
|
+
include Console1984::Freezeable
|
4
|
+
|
5
|
+
def initialize(suspicious_terms)
|
6
|
+
@suspicious_terms = suspicious_terms
|
7
|
+
end
|
8
|
+
|
9
|
+
# Raises a Console1984::Errors::SuspiciousCommand if the term is referenced.
|
10
|
+
def validate(parsed_command)
|
11
|
+
if contains_suspicious_term?(parsed_command)
|
12
|
+
raise Console1984::Errors::SuspiciousCommand
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def contains_suspicious_term?(parsed_command)
|
18
|
+
@suspicious_terms.find do |term|
|
19
|
+
parsed_command.raw_command.include?(term)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Validates console commands.
|
2
|
+
#
|
3
|
+
# This performs an static analysis of console commands. The analysis is meant to happen
|
4
|
+
# *before* commands are executed, so that they can prevent the execution if needed.
|
5
|
+
#
|
6
|
+
# The validation itself happens as a chain of validation objects. The system will invoke
|
7
|
+
# each validation in order. Validations will raise an error if the validation fails (typically
|
8
|
+
# a Console1984::Errors::ForbiddenCommand or Console1984::Errors::SuspiciousCommands).
|
9
|
+
#
|
10
|
+
# Internally, validations will receive a Console1984::CommandValidator::ParsedCommand object. This
|
11
|
+
# exposes parsed constructs in addition to the raw strings so that validations can use those.
|
12
|
+
#
|
13
|
+
# There is a convenience method .from_config that lets you instantiate a validation setup from
|
14
|
+
# a config hash (e.g to customize validations via YAML).
|
15
|
+
#
|
16
|
+
# See +config/command_protections.yml+ and the validations in +lib/console1984/command_validator+.
|
17
|
+
class Console1984::CommandValidator
|
18
|
+
include Console1984::Freezeable
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@validations_by_name = HashWithIndifferentAccess.new
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# Instantiates a command validator that will configure the validations based on the config passed.
|
26
|
+
#
|
27
|
+
# For each key in +config+, it will derive the class Console1984::CommandValidator::#{key.camelize}Validation
|
28
|
+
# and will instantiate the validation passed the values as params.
|
29
|
+
#
|
30
|
+
# For example for this config:
|
31
|
+
#
|
32
|
+
# { forbidden_reopening: [ActiveRecord, Console1984] }
|
33
|
+
#
|
34
|
+
# It will instantiate Console1984::CommandValidator::ForbiddenReopeningValidation passing
|
35
|
+
# +["ActiveRecord", "Console1984"]+ in the constructor.
|
36
|
+
#
|
37
|
+
# # See +config/command_protections.yml+ as an example.
|
38
|
+
def from_config(config)
|
39
|
+
Console1984::CommandValidator.new.tap do |validator|
|
40
|
+
config.each do |validator_name, validator_config|
|
41
|
+
validator_class = "Console1984::CommandValidator::#{validator_name.to_s.camelize}Validation".constantize
|
42
|
+
validator_config.try(:symbolize_keys!)
|
43
|
+
validator.add_validation validator_name, validator_class.new(validator_config)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Adds a +validation+ to the chain indexed by the provided +name+
|
50
|
+
#
|
51
|
+
# Validations are executed in the order they are added.
|
52
|
+
def add_validation(name, validation)
|
53
|
+
validations_by_name[name] = validation
|
54
|
+
end
|
55
|
+
|
56
|
+
# Executes the chain of validations passing a {parsed command}[rdoc-ref:Console1984::CommandValidator::ParsedCommand]
|
57
|
+
# created with the +command+ string passed by parameter.
|
58
|
+
#
|
59
|
+
# The validations are executed in the order they were added. If one validation raises an error, the error will
|
60
|
+
# raise and the rest of validations won't get checked.
|
61
|
+
def validate(command)
|
62
|
+
parsed_command = ParsedCommand.new(command)
|
63
|
+
|
64
|
+
validations_by_name.values.each do |validation|
|
65
|
+
validation.validate(parsed_command)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
attr_reader :validations_by_name
|
71
|
+
end
|
data/lib/console1984/config.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# Container for config options.
|
2
|
+
#
|
3
|
+
# These config options are accessible via first-level reader methods at Console1984.
|
2
4
|
class Console1984::Config
|
3
5
|
include Console1984::Freezeable, Console1984::Messages
|
4
6
|
|
5
7
|
PROPERTIES = %i[
|
6
|
-
session_logger username_resolver
|
8
|
+
session_logger username_resolver shield command_executor
|
7
9
|
protected_environments protected_urls
|
8
10
|
production_data_warning enter_unprotected_encryption_mode_warning enter_protected_mode_warning
|
9
11
|
incinerate incinerate_after incineration_queue
|
@@ -24,16 +26,18 @@ class Console1984::Config
|
|
24
26
|
|
25
27
|
def freeze
|
26
28
|
super
|
27
|
-
protected_urls.freeze
|
29
|
+
[ protected_urls ].each(&:freeze)
|
28
30
|
end
|
29
31
|
|
30
32
|
private
|
31
33
|
def set_defaults
|
32
|
-
self.protected_environments = []
|
33
|
-
self.protected_urls = []
|
34
|
-
|
35
34
|
self.session_logger = Console1984::SessionsLogger::Database.new
|
36
35
|
self.username_resolver = Console1984::Username::EnvResolver.new("CONSOLE_USER")
|
36
|
+
self.shield = Console1984::Shield.new
|
37
|
+
self.command_executor = Console1984::CommandExecutor.new
|
38
|
+
|
39
|
+
self.protected_environments = []
|
40
|
+
self.protected_urls = []
|
37
41
|
|
38
42
|
self.production_data_warning = DEFAULT_PRODUCTION_DATA_WARNING
|
39
43
|
self.enter_unprotected_encryption_mode_warning = DEFAULT_ENTER_UNPROTECTED_ENCRYPTION_MODE_WARNING
|
data/lib/console1984/engine.rb
CHANGED
data/lib/console1984/errors.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Console1984
|
2
2
|
module Errors
|
3
|
+
# Attempt to access a protected url while in protected mode.
|
3
4
|
class ProtectedConnection < StandardError
|
4
5
|
def initialize(details)
|
5
6
|
super "A connection attempt was prevented because it represents a sensitive access."\
|
@@ -7,8 +8,16 @@ module Console1984
|
|
7
8
|
end
|
8
9
|
end
|
9
10
|
|
11
|
+
# Attempt to execute a command that is not allowed. The system won't
|
12
|
+
# execute such commands and will flag them as sensitive.
|
10
13
|
class ForbiddenCommand < StandardError; end
|
14
|
+
|
15
|
+
# A suspicious command was executed. The command will be flagged but the system
|
16
|
+
# will let it run.
|
17
|
+
class SuspiciousCommand < StandardError; end
|
18
|
+
|
19
|
+
# Attempt to incinerate a session ahead of time as determined by
|
20
|
+
# +config.console1984.incinerate_after+.
|
11
21
|
class ForbiddenIncineration < StandardError; end
|
12
|
-
class ForbiddenCodeManipulation < StandardError; end
|
13
22
|
end
|
14
23
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# Prevents accessing trail model tables when executing console commands.
|
2
|
-
module Console1984::ProtectedAuditableTables
|
2
|
+
module Console1984::Ext::ActiveRecord::ProtectedAuditableTables
|
3
3
|
include Console1984::Freezeable
|
4
4
|
|
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.
|
8
|
+
if Console1984.command_executor.executing_user_command? && sql =~ auditable_tables_regexp
|
9
9
|
raise Console1984::Errors::ForbiddenCommand, "#{sql}"
|
10
10
|
else
|
11
11
|
super(*args, **kwargs)
|
@@ -25,6 +25,4 @@ module Console1984::ProtectedAuditableTables
|
|
25
25
|
def auditable_models
|
26
26
|
@auditable_models ||= Console1984::Base.descendants
|
27
27
|
end
|
28
|
-
|
29
|
-
include Console1984::Freezeable
|
30
28
|
end
|