Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: redis sandboxing #50

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

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?

lib/safer_rails_console/patches/sandbox/redis_readonly.rb Outdated Show resolved Hide resolved
lib/safer_rails_console/patches/sandbox/redis_readonly.rb Outdated Show resolved Hide resolved
@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
Contributor

@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 = [
Copy link
Contributor

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.

Copy link
Contributor

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'
Copy link
Contributor

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(
Copy link
Contributor

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)
Copy link
Contributor

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)
Copy link
Contributor

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
Copy link
Contributor

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
Contributor

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