Skip to content

Username support when connecting to REDIS #295

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

Closed
epicserve opened this issue Mar 3, 2022 · 7 comments
Closed

Username support when connecting to REDIS #295

epicserve opened this issue Mar 3, 2022 · 7 comments

Comments

@epicserve
Copy link

I created a simple "hello world" chat application running locally using docker-compose which is running redis:6. However, when I deployed to a production environment on AWS it didn't work because our ElastiCache Redis Cluster using the 6.2.5 requires a username and password in order to connect.

If you are using docker-compose for development, you can reproduce the error if you configure your Redis service in the following way.

  redis:
    container_name: redis
    image: redis:6
    command: ['redis-server', '/etc/redis/redis.conf']
    volumes:
      - ./redis.conf:/etc/redis/redis.conf
      - redis-data:/data

Then in your redis.conf in your project add the following:

appendonly yes
user myusername +@all allkeys on >my-random-password

Then in your Django settings try the following:

ASGI_APPLICATION = "config.asgi.application"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": ['redis://myusername:my-random-password@redis:6379'],
        },
    },
}

Relevant package versions:

Python Version: 3.9.10
channels==3.0.4
channels-redis==3.3.1
Django==3.2.12
django-redis-cache==3.0.0
django-redis-sessions==0.6.2
aioredis==1.3.1

In production, I'm running Channels with gunicorn/uvicorn.

This is a traceback of what is happening locally, which leads me to believe that Channels will need to be upgraded to using aioredis 2.0 as well as a fix to this package. It would also be good if the README and docs could be upgraded to show how you're supposed to configure a Redis host that needs a username and/or password.

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 451, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 414, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 442, in wait_for
    return await fut
  File "/usr/local/lib/python3.9/site-packages/asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 455, in thread_handler
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/contrib/auth/mixins.py", line 128, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/opt/project/apps/accounts/views.py", line 22, in post
    async_to_sync(channel_layer.group_send)(f"push_message_{user.username}", data)
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 204, in __call__
    return call_result.result()
  File "/usr/local/lib/python3.9/concurrent/futures/_base.py", line 439, in result
    return self.__get_result()
  File "/usr/local/lib/python3.9/concurrent/futures/_base.py", line 391, in __get_result
    raise self._exception
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 270, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/channels_redis/core.py", line 671, in group_send
    async with self.connection(self.consistent_hash(group)) as connection:
  File "/usr/local/lib/python3.9/site-packages/channels_redis/core.py", line 902, in __aenter__
    self.conn = await self.pool.pop()
  File "/usr/local/lib/python3.9/site-packages/channels_redis/core.py", line 93, in pop
    conn = await self.create_conn(loop)
  File "/usr/local/lib/python3.9/site-packages/channels_redis/core.py", line 79, in create_conn
    return await aioredis.create_redis_pool(**kwargs)
  File "/usr/local/lib/python3.9/site-packages/aioredis/commands/__init__.py", line 188, in create_redis_pool
    pool = await create_pool(address, db=db,
  File "/usr/local/lib/python3.9/site-packages/aioredis/pool.py", line 58, in create_pool
    await pool._fill_free(override_min=False)
  File "/usr/local/lib/python3.9/site-packages/aioredis/pool.py", line 383, in _fill_free
    conn = await self._create_new_connection(self._address)
  File "/usr/local/lib/python3.9/site-packages/aioredis/connection.py", line 133, in create_connection
    await conn.auth(password)
  File "/usr/local/lib/python3.9/site-packages/aioredis/util.py", line 52, in wait_ok
    res = await fut

Exception Type: ReplyError at /accounts/send-push-message/
Exception Value: WRONGPASS invalid username-password pair or user is disabled.
@ipmb
Copy link
Contributor

ipmb commented Mar 3, 2022

#285 would be required for this afaict

@carltongibson
Copy link
Member

It looks like it is trying to connect:

  File "/usr/local/lib/python3.9/site-packages/aioredis/connection.py", line 133, in create_connection
    await conn.auth(password)
  File "/usr/local/lib/python3.9/site-packages/aioredis/util.py", line 52, in wait_ok
    res = await fut

… but I don't know the details of what's possible or not.

This is a traceback of what is happening locally, which leads me to believe that Channels will need to be upgraded to using #285 as well as a fix to this package.

I'm not seeing the connection 100% from the information given. (Is it clear aioredis doesn't support passwords?)
If so though this is a duplicate of #285.

... as well as a fix to this package.

Is there another fix needed?

... show how you're supposed to configure a Redis host that needs a username and/or password.

I'd rather link to the right place than reproduce the connection docs TBH. It's just a pass-through to the underlying library.
But such a link, sure.

@ipmb
Copy link
Contributor

ipmb commented Mar 3, 2022

My read is that the underlying library doesn't support it. It was added here, but never made it into an official release afaict. The underlying library is now unsupported/unmaintained, so I think #285 is the blocker.

@carltongibson
Copy link
Member

OK thanks @ipmb — let's close in favour of #285.

@epicserve
Copy link
Author

@ipmb and @carltongibson,

Thank you for looking into this. On a second pass, I can confirm channels-redis is just passing the address on to aioredis. If you put a break on here, you'll see that kwargs is set to something like the following.

{'minsize': 1, 'maxsize': 1, 'address': 'redis://redis-user-name:some-password@redis:6379'}

@ipmb
Copy link
Contributor

ipmb commented Mar 4, 2022

Yes, that's true, but it doesn't matter. Even if you passed the username down, aioredis wouldn't accept it or do the right thing with it.

@epicserve
Copy link
Author

@ipmb, right. I saw your comments on #285.

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

No branches or pull requests

3 participants