django-cacheops
django-cacheops copied to clipboard
Permissions issue writing to redis
Redis is running on an external service (AWS) and I'm having trouble configuring cacheops to talk to it without getting this error:
redis.exceptions.NoPermissionError: this user has no permissions to access one of the keys used as arguments
I had no trouble setting up Django's main cache to use my prefix:
CACHES = {
"default": {
...
"KEY_PREFIX": config.REDIS_PREFIX, # loaded from an env var
...
}
}
# Then from a Django shell:
from django.core.cache import cache
cache.set("foo", "bar")
cache.get("foo")
'bar'
I'm having trouble wiring up cacheops to work the same way. Docs say we cannot use a simple string, but must reference a function or lambda:
CACHEOPS_PREFIX = lambda query: ...
# or
CACHEOPS_PREFIX = 'some.module.cacheops_prefix'
So, two questions:
-
Why can't we use a simple string here? I'm not following the point of requiring a lambda or function to set this var, when a string works fine for the main Django cache settings.
-
Even when I do set it up as a callable, still get the permissions error.
If I don't create the setting CACHEOPS_PREFIX , I get the permissions error. If I do set it, I get the permissions error.
def get_cacheops_prefix():
return config.REDIS_PREFIX
# Neither of these work
#CACHEOPS_PREFIX = "myapp.settings.get_cacheops_prefix"
#CACHEOPS_PREFIX = lambda query: get_cacheops_prefix()
Since Django's main cache works fine, it feels like the Permissions error is red herring or mistake in my configuration, but I can't see what. Maybe this isn't about the prefix? But if not that, then what? Thanks for a clue.
Django cache does not support callable prefix, so it's just string, here things are different.
CACHEOPS_PREFIX = lambda _: "your_prefix"
Should work. If not then need to look at particular key you get permission error on.
I dug into this a bit more and found the issue. If you are using Redis' ACL to restrict a user to a specific key namespace, you can replicate the problem. In Redis add a user like this:
ACL SETUSER user on nopass ~user/* +@all
Now set CACHEOPS_PREFIX = lambda _: "user/" and connect to redis://user@localhost:6379/0.
When you query the database the cache_thing.lua script will get called with 3 keys:
"user/""user/q:..."""
Redis won't run the script because the last key cannot be accessed by this user and you'll get this error:
NOPERM this user has no permissions to access one of the keys used as arguments
I'm not deeply familiar with how this library works, but I submitted a PR which seems to fix the issue in #423
Thanks very much for the PR @ipmb and thanks for the speedy merge @Suor . Just need to get this into pypi and we'll be off and running.