-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
fix(ldap) cache key to work when plugin is configured globally #3354
Conversation
I will give it a go, may take a day or so to get there, my kong deployments are currently done by pulling a docker image, so I need to work out how to drop this into my setup. |
kong/plugins/ldap-auth/access.lua
Outdated
local function authenticate(conf, given_credentials) | ||
local given_username, given_password = retrieve_credentials(given_credentials, conf) | ||
if given_username == nil then | ||
return false | ||
end | ||
|
||
local route_id = conf.route_id or conf.api_id | ||
local cache_key = "ldap_auth_cache:" .. route_id .. ":" .. given_username | ||
local cache_key = acl_cache_key(conf, given_username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is calculated on every request. We better cache the calculated key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, the calculation is not very intensive. Maybe caching is even slower than calculating MD5 out of small string? Not sure if it is worth considering added complexity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you leave the username out of the hash, you can create the entire key and store it in a weak table. That would be a single table lookup, followed by the username concatenation.
}, ":")) | ||
} | ||
|
||
return concat(cache_key, ":") | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe also add a test that reproduces the original problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the hash solution for other plugin instances using the same ldap backend. More performant and less resources. 👍
pinging @shashiranjan84 since he did the original work on this. @bungle maybe add a small comment in the |
kong/plugins/ldap-auth/access.lua
Outdated
@@ -84,14 +86,31 @@ local function load_credential(given_username, given_password, conf) | |||
return {username = given_username, password = given_password} | |||
end | |||
|
|||
|
|||
local function acl_cache_key(conf, username) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this name intentional acl_cache_key
, not a big deal though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops... how did I miss that... good catch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied that name from unit tests. I can rename both.
kong/plugins/ldap-auth/access.lua
Outdated
}, ":")) | ||
} | ||
|
||
return concat(cache_key, ":") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a lot more efficient to follow the approach taken by dao:cache_key()
rather than paying the cost of 2 short-lived tables, the double concatenation operation, and the md5
hash. Any reason for now using a simple string.format
instead? Combined with @Tieske's comment about caching the cache key prefix (that of the plugin configuration), and simply use the username
as the dynamic component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I will change that. A lot more in this case might be a few microseconds, but of course better to do it like that. Not sure though, should we use something else than MD5
. Maybe requiring lua-resty-string
and using SHA256
instead. Maybe not worth it, when I remove username
from the hash.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, as always, it isn't about making that particular piece of the code run a few microseconds faster, but rather prevent the spreading of anti-patterns and ensure that overall, the proxy still performs relatively well in hot code paths. To avoid accumulating performance penalties when they can be avoided. It is a continuous effort.
In this case if we cache the key and only rotate the username
part, we can get away with the current approach, sure.
I'm not sure why the hashing is required though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the resulting string is a lot smaller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the only benefit I am seeing as well (in which case md5 should be just fine?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A key without hashing:
ldap_auth_cache:ec2-54-172-82-117.compute-1.amazonaws.com:389:ou=scientists,dc=ldap,dc=mashape,dc=com:uid:2:einstein
A key with hashing:
ldap_auth_cache:aec022a3d1d6590c4432b4bc65433e2e:einstein
ab9ae12
to
cfec416
Compare
@Tieske, @thibaultcha, @shashiranjan84, Ok, I tried to fix all your concerns. Let me know what you think about it now. |
cfec416
to
401a820
Compare
The CI build seems to consistently error on the following step:
I restarted both builds to make sure that this wasn't a flaky setup. |
conf.base_dn, | ||
conf.attribute, | ||
conf.cache_ttl | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should remove case sensitivity from the cache-key for those elements that are not case sensitive (eg. hostname, haven't looked into the ldap specifc ones).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LDAP specific ones are usually case-insensitive
, but you may possibly configure them to be case-sensitive
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then the safe way would be to keep them case-sensitive, so that only leaves the hostname to update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
http://ldapwiki.com/wiki/Distinguished%20Name%20Case%20Sensitivity
(I don't have a courage to make other than host
case-insensitive, EVEN though in most sane cases they all are case-insensitive, including the username).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aren't the host and port properties only used to connect to the ldap server?
@thibaultcha somewhat related to this, in the light of plugin-api spec, we could consider dropping the weak table pattern and use the config table instead.
we could define it as:
we might even consider to add a None of this for this PR though. |
@Tieske, yes I was looking forward for that, but couldn't find a place currently to do that. Your other comments are good (case insensitivity), also I need to check that erroring test. |
401a820
to
bf89d4d
Compare
Summary
Changes the way how LDAP cache key in constructed. Previously it didn't share cache with similarly configured LDAP plugins. And more importantly, it was broken when configured as a global plugin (that was reported with #3335)
Full changelog
Issues resolved
Fix #3335