socketry / async-redis

MIT License
83 stars 18 forks source link

NOAUTH Authentication Required #34

Closed amjanoni closed 3 years ago

amjanoni commented 3 years ago

Hello,

I'd like to know if it's possible to use this package with Redis Authentication? I'm using the rediss://:[password]@[hostname]:[port]/[db] format but even though I'm having issues with the Authentication.

/usr/local/bundle/gems/protocol-redis-0.6.0/lib/protocol/redis/connection.rb:120:in `read_object': NOAUTH Authentication required. (Protocol::Redis::ServerError)
        from /usr/local/bundle/gems/async-redis-0.5.3/lib/async/redis/client.rb:124:in `block in call'
        from /usr/local/bundle/gems/async-pool-0.3.5/lib/async/pool/controller.rb:93:in `acquire'
        from /usr/local/bundle/gems/async-redis-0.5.3/lib/async/redis/client.rb:119:in `call'
        from /usr/local/bundle/gems/protocol-redis-0.6.0/lib/protocol/redis/methods/generic.rb:50:in `exists'
        from /app/lib/storage/indexes.rb:49:in `initialize'
        from /app/lib/storage/indexes.rb:25:in `new'
        from /app/lib/storage/indexes.rb:25:in `index_by'
        from /app/storages/client.rb:12:in `<class:Client>'
        from /app/storages/client.rb:1:in `<top (required)>'
        from /app/lib/storage.rb:193:in `require'
        from /app/lib/storage.rb:193:in `each'
        from /app/lib/storage.rb:193:in `block in <top (required)>'
        from /usr/local/bundle/gems/async-1.28.9/lib/async/task.rb:265:in `block in make_fiber'
ioquatix commented 3 years ago

This is a little bit tricky. Yes, it's possible, but it it currently isn't that easy.

We would need to add a hook here:

https://github.com/socketry/async-redis/blob/509ea5ee482e972b8db6e17b8dcdd5977ceec791/lib/async/redis/client.rb#L139

This should do the authentication and any other setup (i.e. select database).

ioquatix commented 3 years ago

What you could do is this:

class AuthenticatedRESP2
  def initialize(credentials)
    @credentials = credentials
  end

  def client(stream)
    client = Async::Redis::Protocol::RESP2
    client.auth(*@credentials)
    return client
  end
end

client = Client.new(..., protocol: AuthenticatedRESP2.new("username", "password"))
ioquatix commented 3 years ago

It looks like our AUTH implementation might need an optional username:

https://github.com/socketry/protocol-redis/blob/86d111c6dcee10694c3eb5db6c0d8a4cf5e12b88/lib/protocol/redis/methods/connection.rb#L27-L32

ioquatix commented 3 years ago

Okay, I released protocol-redis v0.6.1 which supports the above multi-argument auth call (introduced Redis 6). Can you try it out with the above example?

tonywok commented 3 years ago

class AuthenticatedRESP2 def initialize(credentials) @credentials = credentials end

def client(stream) client = Async::Redis::Protocol::RESP2 client.auth(*@credentials) return client end end

client = Client.new(..., protocol: AuthenticatedRESP2.new("username", "password"))

I'm guessing this is just meant to be psuedo code?

Couple things I'm running into... The protocol kwarg appears to be positional.

As written, I get:

NoMethodError: undefined method `auth' for Async::Redis::Protocol::RESP2:Module

Looking at the implementation maybe we're missing self.? With that change I'm still getting:

NoMethodError: undefined method `auth' for #<Async::Redis::Protocol::RESP2::Connection:0x0000556f3c619148