Skip to content

Conversation

@gkorland
Copy link
Contributor

No description provided.

Copy link
Contributor

@sazzad16 sazzad16 left a comment

Choose a reason for hiding this comment

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

Please use 2 spaces for a tab in entire implementation.

@sazzad16 sazzad16 changed the title Allow renaming Command (#1817) Support rename-command (#1817) Jul 15, 2018
@sazzad16
Copy link
Contributor

LGTM!

@marcosnils @HeartSaVioR

@sazzad16 sazzad16 added this to the 2.10.0 milestone Jul 15, 2018
@marcosnils
Copy link
Contributor

What if we also add a rename method to the Jedis class which takes a Command and a String as a rename?. The reason why I'm suggesting this is because from the API perspective Jedis users will expect to see the rename method. This is how @mp911de did it in lettuce also (https://github.com/lettuce-io/lettuce-core/blob/dde37483a31215ebf17f7141fea6454971ea9a08/src/test/java/io/lettuce/core/commands/KeyCommandTest.java#L212-L214)

Thoughts?

@sazzad16
Copy link
Contributor

@marcosnils Your provided link is about rename command which is already implemented in Jedis

https://github.com/xetorthio/jedis/blob/d1fb17ce3021f8bac135aef3fd306d62c877c13c/src/main/java/redis/clients/jedis/Jedis.java#L304-L308

But this PR is about supporting rename-command of Redis Security.

@marcosnils
Copy link
Contributor

@smadasu you're right. How about if we add the renameCommand or something similar to the Jedis API.
I'm not entirely sure if doing Protocol.<CMD>.rename("something") is the cleanest way from the API perspective.

@sazzad16
Copy link
Contributor

@marcosnils

How about if we add the renameCommand or something similar to the Jedis API.

  1. What we have in Jedis/BinaryJedis/JedisCluster etc are Redis commands. But rename-command is not a Redis command.

  2. Unlike Redis commands, rename-command is done by configuration file.

I'm not entirely sure if doing Protocol..rename("something") is the cleanest way from the API perspective.

I'm also concerned about that. But I couldn't find another way, let alone a better one, to support this feature.

I can see only two options regarding this. Either use an available solution or leave that feature out from supporting.

@gkorland
Copy link
Contributor Author

@marcosnils rename-command shouldn't be part of the API since as @sazzad16 mentioned a command is renamed using the Redis configuration file. Meaning, a user shouldn't really rename methods in runtime.

@sazzad16 I think it will be a shame to leave this capability aside since command rename is a simple but efficient security method. Which indeed doesn't add any really security layer but protect from most of crawlers attacks.

@marcosnils
Copy link
Contributor

ename-command shouldn't be part of the API since as @sazzad16 mentioned a command is renamed using the Redis configuration file. Meaning, a user shouldn't really rename methods in runtime.

Right. Still the Protocol.<CMD>.rename("something") doesn't convince me. Can we try to look for an alternative for this?. Maybe check how / if other libraries are doing it?

@gkorland
Copy link
Contributor Author

gkorland commented Jul 16, 2018

@marcosnils node_redis is doing it on client initialization

redis.createClient([options])
*rename_commands* -
Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: { KEYS : "DO-NOT-USE" } . 

@gkorland
Copy link
Contributor Author

Same with .NET client StackExchange.Redis

var commands = new Dictionary<string,string> {
        { "info", null }, // disabled
        { "select", "use" }, // renamed to SQL equivalent for some reason
};

var options = new ConfigurationOptions {
    // ...
    CommandMap = CommandMap.Create(commands),
    // ...
}

@gkorland
Copy link
Contributor Author

@marcosnils I don't think our current design fit adding it constructor settings

@marcosnils
Copy link
Contributor

Maybe we can resurrect #1787 and add it there? @gkorland WDYT?

@sazzad16
Copy link
Contributor

@marcosnils Don't know if it's relevant, but a note: currently, there is a way to alter localhost in Jedis which is done without constructor.

https://github.com/xetorthio/jedis/blob/d1fb17ce3021f8bac135aef3fd306d62c877c13c/src/main/java/redis/clients/jedis/HostAndPort.java#L120-L124

@gkorland
Copy link
Contributor Author

@marcosnils I don't think #1787 will help here unless we also moving from Enums and make a bigger redesign. It's probably cleaner to do it as part of the constructor but are we ready to make this refactor?

As @sazzad16 mentioned I think this pattern is already being used in the product for another rare use case so I think it can be a good compromise.

@marcosnils
Copy link
Contributor

As @sazzad16 mentioned I think this pattern is already being used in the product for another rare use case so I think it can be a good compromise.

I'm not against this change, I'm just trying to evaluate all other alternatives as I'm not 100% convinced about this approach. As you're saying, the HostAndPort case is rare. In this case, the rename feature is something common to Redis / Jedis and there might be some other things like this in the future.

I guess we could move forward with this approach and refactor it later in the future, but taking the opportunity that we'll be probably releasing 3.0 next, I'd like to take advantage of the interface breaking changes and do it the right way.

daemonize yes
protected-mode no
port 6386
requirepass foobared
Copy link
Contributor

@sazzad16 sazzad16 Jul 20, 2019

Choose a reason for hiding this comment

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

Test requires instance at 6386 port to be password-less. Either create a new instance or create a new one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"a new instance or create a new one"? what is the different between "new instance" and "new one"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oops!

"Either use password-less instance or create a new one."

@sazzad16
Copy link
Contributor

@gkorland I vote to include this feature. IMO, adding solution for one configuration is far better than not having solution for multiple configuration.

And I'm okay with your implementation. Not to mention, we've waited a year for an alternate solution.

@jaipreet-chhatwal
Copy link

@gkorland @sazzad16 : When we configure Redis with Sentinel for HA, arent we suppoosed to configure the same Redis password in every instance. Isn't this expected already that we need to have same configuration across nodes.
So i am not able to understand the problem with
"adding solution for one configuration is far better than not having solution for multiple configuration." since we are already "
Please correct me if i am missing a very basic point and not on same page with you guys.

Also, can we conclude on the version in which this rename-command feature will be supported.

@sazzad16
Copy link
Contributor

@jaipreet-chhatwal

Isn't this expected already that we need to have same configuration across nodes.

Yes and No.

Within same sentinel, it is expected that the nodes within that sentinel are of same configuration. For example, they are expected to have same password.

But Jedis is not limited to connect with only one Redis instance/sentinel/cluster. It allows you to connect with many of them at once. So you can set up two different sentinels (two different group of nodes, say A and B) and connect with them simultaneously within same application using Jedis. Those two set of sentinel nodes are not required to have same configuration. For example, both set of nodes A and B are not required to have same password, even though all nodes of sentinel A are expected to have same password as well as all nodes of sentinel B are expected to have same password.

I hope this clears your confusion about my statement.

@sazzad16
Copy link
Contributor

@jaipreet-chhatwal

can we conclude on the version in which this rename-command feature will be supported.

Not yet.

@gkorland
Copy link
Contributor Author

@sazzad16 if we agree this solution is better than nothing, let's mark it as 3.2.0?

@sazzad16 sazzad16 added this to the 3.2.0 milestone Jul 24, 2019
@sazzad16
Copy link
Contributor

@gkorland sure thing!

@marcosnils It has been a year. Humbly speaking, we have waited enough for an alternate solution.

}

public void rename(final String newName) {
raw = SafeEncoder.encode(newName);
Copy link
Contributor

Choose a reason for hiding this comment

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

Couldn't this be an issue in multithreading? Synchronized/Lock may be required here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, but volatile should do, I'm trying to find a way to avoid the performance penalty on each getRaw() call

Copy link
Contributor

Choose a reason for hiding this comment

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

  • +1 to volatile (or AtomicReference), at the moment it's not though, so we need to update that to either volatile or AtomicReference.
  • We should make this fail (and have tests for) if newName is:
    • null
    • empty
    • an existing command name

@sazzad16 sazzad16 modified the milestones: 3.2.0, 3.3.0 Nov 25, 2019
@sazzad16 sazzad16 modified the milestones: 3.3.0, 3.4.0 Mar 14, 2020
@sazzad16 sazzad16 modified the milestones: 3.4.0, 3.5.0 Nov 26, 2020
@sazzad16 sazzad16 modified the milestone: 3.5.0 Dec 9, 2020
jedis.del("mykey");
fail("'DEL' command should be unknown");
} catch (JedisDataException expected) {
assertEquals("ERR unknown command 'DEL'", expected.getMessage());
Copy link
Contributor

@yangbodong22011 yangbodong22011 Jan 19, 2021

Choose a reason for hiding this comment

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

Suggested change
assertEquals("ERR unknown command 'DEL'", expected.getMessage());
// We need use a regex for the error message, because it may has different format
// 1, ERR unknown command 'DEL'
// 2, ERR unknown command `del`, with args beginning with: `abc` (Redis 6.2)
Assert.assertTrue(expected.getMessage().matches("ERR unknown command .DEL.*"));

@sazzad16 sazzad16 modified the milestones: 3.5.0, 3.6.0 Jan 19, 2021
}

public void rename(final String newName) {
raw = SafeEncoder.encode(newName);
Copy link
Contributor

Choose a reason for hiding this comment

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

  • +1 to volatile (or AtomicReference), at the moment it's not though, so we need to update that to either volatile or AtomicReference.
  • We should make this fail (and have tests for) if newName is:
    • null
    • empty
    • an existing command name

@sazzad16 sazzad16 removed this from the 3.6.0 milestone Mar 8, 2021
@sazzad16
Copy link
Contributor

@gkorland Command renaming is deprecated in Redis. See redis/redis@7604ab7
Should we close this PR? Or, keep this PR open for discussion?

@gkorland
Copy link
Contributor Author

Lets close

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.

7 participants