Skip to content

Conversation

@mileszim
Copy link

This adds Redis sandboxing to safer_rails_console.

It allows for reading, but any attempt to call a write method raises an error

@mileszim mileszim marked this pull request as ready for review August 28, 2022 09:10
Copy link

@will89 will89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! Would you mind updating the README with this new functionality?

@mileszim
Copy link
Author

reminder to self: add this too https://github.com/redis-rb/redis-client

@mileszim
Copy link
Author

@will89 @mattsmith0308 @jturkel any updates?

Copy link
Contributor

@mjsmithnh mjsmithnh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I'm not a Redis expert by any means but I'm assuming this can't be bypassed via something like a subquery, or if that is the case we don't care?

@jturkel
Copy link
Member

jturkel commented Jan 12, 2023

@gremerritt - Mind taking a look at this PR?

Copy link

@gremerritt gremerritt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! This has been on my backlog of things to think about for a while, it'll be a great addition.

A few high-level thoughts/questions:

  • Have you thought about using ACLs on the server instead of manually blocking commands on the client? It would only work for redis 6+, but it (might) involve less client patching.
  • I notice that scripting commands are missing from the whitelist (eg. evalsha). We have some scripts that are effectively read-only. It's a grey area because they could just as well be mutating. I'm also inclined to say we should allow load commands. We have our own redis client that registers necessary scripts effectively at boot time, and we'd need a solution there to not load scripts in certain cases.
  • redis-rb uses redis-client internally, so eventually we may be able to drop the ::Redis support. I'm guessing we want to support redis-rb v4 for now though.

module Patches
module Sandbox
module RedisReadonly
READ_COMMANDS = [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm vaguely worried about this list falling out of date as new commands are added, but I think it's fine since we're whitelisting.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also a nit, can we alphabetize these?

'zrevrangebylex', 'sunion', 'randomkey', 'zrevrank', 'xrange', 'xpending', 'hgetall', 'getrange', 'exists',
'keys', 'georadius_ro', 'lolwut', 'hscan', 'object', 'zlexcount', 'type', 'geohash', 'touch', 'hkeys',
'strlen', 'scard', 'substr', 'zinter', 'srandmember', 'mget', 'xinfo', 'geosearch', 'zunion', 'xread',
'pfcount', 'xrevrange', 'sscan', 'memory', 'bitfield_ro', 'dump', 'host:', 'sinter', 'getbit', 'zcard'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is host: correct here?


def self.raise_exception_on_write_command(command, service = ::Redis)
unless READ_COMMANDS.include?(command.downcase.to_s)
raise service.to_s.constantize::CommandError.new(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why service.to_s.constantize?

end

module RedisPatch
def process(commands)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work for pipelined/multi commands? I think this may only catch this first command being executed.

end

module RedisClientPatch
def call(commands, redis_config)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise I don't think this covers pipelines or multis?

end
end

module RedisClientPatch

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redis-client has great middleware support. It might be easier to implement this via a middleware (in the config object).

@gremerritt
Copy link

Re: the scripting commands, let's go forward with what you have currently (ie. blocking scripting commands). Can you add a config-level toggle to disable the new redis support though? We'll likely come back to this and add some additional scripting configuring support, but I don't want to block you from getting this out either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants